scheduleNotification
создаёт нотификации с одним и тем же id. Новые нотификации перетирают старые. Лучше в качестве id использовать или константы, или что-то связанное с заголовком: "\(content.title.hash)"
.func scheduleNotification(inSeconds seconds:TimeInterval, text: String, completion: (Bool) -> ())
. Тогда можно будет его использовать для создания нотификации: content.title = text
.deinit
нужно убрать совсем. Он удаляет вашу нотификацию при удалении экрана из памяти.viewDidLoad()
из этого же класса. deleteFood(IndexPath)
и отдельно var animatableChanges: ((OldData, NewData) -> Void)?
куда View может засунуть свой байндинг. Такой подход позволяет ViewModel обновлять вьюху тогда, когда она посчитает нужным, а с другой стороны держать код всех байндингов в одном месте (к примеру, в специальном методе, вызываемом из viewDidLoad
). func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
URLSession.shared.dataTask(with: navigationAction.request) { [weak webView] (data, _, _) in
decisionHandler(.cancel)
guard let html = data.flatMap({ String(data: $0, encoding: .utf8) }) else {
return
}
webView?.loadHTMLString(html, baseURL: navigationAction.request.url)
}.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
textField.addTarget(self, action: #selector(editingBegan(_:)), for: .editingDidBegin)
textField.addTarget(self, action: #selector(editingChanged(_:)), for: .editingChanged)
textField.addTarget(self, action: #selector(editingEnded(_:)), for: .editingDidEnd)
}
@objc func editingBegan(_ textField: UITextField) {
//пользователь попал в поле, но еще ничего не ввел
}
@objc func editingChanged(_ textField: UITextField) {
//текст изменился
}
@objc func editingEnded(_ textField: UITextField) {
//ввод окончен, к примеру нажали "return" на клавиатуре
}
self.whiteList.insert(link)
guard !whiteList.contains(link) else {
return
}
let alertController = ...
typealias ResultsArray = [[(homeTeam: (name: String, score: String), guestTeam: (name: String, score: String))]]
//для сравнения, ваша структура:
typealias YourStructure = [[[String: String]]
class ViewController: NSViewController {
@IBOutlet private weak var usernameLabel: NSTextField!
func viewDidLoad() {
super.viewDidLoad()
let someInstance = //тут мы находим ваш экземляр (к примеру, он синглтон)
someInstance.delegate = self
}
}
extension ViewController: SomeInstanceDelegate {
func updateUsernameOnUI(_ username: String) {
usernameLabel.stringValue = username
}
}
class ViewController: NSViewController {
@IBOutlet private weak var usernameLabel: NSTextField!
func viewDidLoad() {
super.viewDidLoad()
let someInstance = //тут мы находим ваш экземляр (к примеру, он синглтон)
someInstance.addObserver(self)
}
}
extension ViewController: SomeInstanceObserver {
func usernameUpdated(_ username: String) {
usernameLabel.stringValue = username
}
}
class ViewController: NSViewController {
@IBOutlet private weak var usernameLabel: NSTextField!
func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(usernameUpdate(:)),
name: Notification.Name("usernameUpdated"), object: nil)
}
}
extension ViewController {
@objc func usernameUpdate(_ notification: Notification) {
guard let username = notification.userInfo?["username"] as? String else {
return
}
usernameLabel.stringValue = username
}
}
UICollectionViewDelegateFlowLayout
и был задан в качестве delegate
у коллекции. Тогда вы сможете задать размер ячейки, которая заполнит экран по ширине:extension /*Ваш класс*/ : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: UIScreen.main.bounds.size.width - 2*/*размер вашего отступа*/, height: /*желаемая высота*/)
}
}
DispatchQueue.main.async { [weak self] in
self?.label.text = temp
}
weakSelf
не стоит. просто [weak self]
отлично работает. В такой ситуации код читается легче и подсветка синтаксиса работает корректнее;if let source = parsedObject as? [String: Any], let text = source["text"] as? [String] {
for temp in text {
print(temp)
self?.label.text = temp
}
}
var cycles = 0
, поставьте условие if i + 1 > exersiseName.count
первым и модифицируйте следующим образом:if i + 1 > exersiseName.count { //Конец цикла
count+=1
if (count >= sets) {
timerLabel.text = "0"
timer.invalidate()
timerRunning = false
}else{
i = 0
}
} //важно: не надо ставить здесь else
if ....
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.messages.count-1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: true)