Выполните метод, когда значение переменной изменяется в Swift

Мне нужно выполнить функцию при изменении значения переменной.

У меня есть одноэлементный класс, содержащий общую переменную, называемую labelChange . Значения этой переменной берутся из другого класса под названием « Model . У меня есть два класса VC, один из которых имеет кнопку и метку, а вторую – только кнопку.

Когда нажата кнопка в первом классе VC, я обновляю эту метку с помощью этой функции:

 func updateLabel(){ self.label.text = SharingManager.sharedInstance.labelChange } 

Но я хочу вызвать тот же метод всякий раз, когда labelChange значение labelChange . Поэтому при нажатии кнопки я обновляю значение labelChange и когда это произойдет, я хочу обновить метку новым значением labelChange . Также во втором VC я могу обновить значение labelChange но я не могу обновить метку, когда это значение изменилось.

Возможно, свойства – это решение, но может ли кто-нибудь показать мне, как это сделать.

Отредактировано второй раз:

Singleton Класс:

 class SharingManager { func updateLabel() { println(labelChange) ViewController().label.text = SharingManager.sharedInstance.labelChange } var labelChange: String = Model().callElements() { willSet { updateLabel() } } static let sharedInstance = SharingManager() } 

Первый VC:

 class ViewController: UIViewController { @IBOutlet weak var label: UILabel! @IBAction func Button(sender: UIButton) { SViewController().updateMessageAndDismiss() } } 

Второй VC:

 func updateMessageAndDismiss() { SharingManager.sharedInstance.labelChange = modelFromS.callElements() self.dismissViewControllerAnimated(true, completion: nil) } @IBAction func b2(sender: UIButton) { updateMessageAndDismiss() } 

Я сделал некоторые улучшения, но мне нужно ссылаться на ярлык из первого класса VC в singleton. Поэтому я обновлю эту метку VC в singleton.

Когда я печатаю значение labelChange значение обновляется, и все в порядке. Но когда я пытаюсь обновить это значение на ярлыке от singleton, я получаю сообщение об ошибке:

неожиданно найдено нуль при развертывании необязательного значения

и ошибка указывает на 4-ю строку одноточечного класса.

Вы можете просто использовать наблюдателя свойств для переменной, labelChange и вызвать функцию, которую вы хотите вызвать внутри didSet (или willSet если вы хотите вызвать ее до ее установки):

 class SharingManager { var labelChange: String = Model().callElements() { didSet { updateLable() } } static let sharedInstance = SharingManager() } 

Это объясняется в Property Observer .

Я не уверен, почему это не сработало, когда вы его пробовали, но если у вас проблемы, потому что функция, которую вы пытаетесь вызвать ( updateLable ), находится в другом классе, вы можете добавить переменную в класс SharingManager для хранения функция, вызываемая при didSet функции didSet , которая в этом случае будет установлена ​​в updateLable .

Отредактировано:

Поэтому, если вы хотите отредактировать метку из ViewController, вам нужно иметь эту функцию updateLable () в классе ViewController для обновления метки, но сохранить эту функцию в классе singleton, чтобы она могла знать, какую функцию вызывать:

 class SharingManager { static let sharedInstance = SharingManager() var updateLable: (() -> Void)? var labelChange: String = Model().callElements() { didSet { updateLable?() } } } 

а затем установите его в любом классе, который у вас есть функция, которую вы хотите вызывать, например (предполагается, что updateLable – это функция, которую вы хотите вызвать):

 SharingManager.sharedInstance.updateLable = updateLable 

Конечно, вы захотите убедиться, что контроллер вида, который отвечает за эту функцию, все еще существует, поэтому класс singleton может вызывать функцию.

Если вам нужно вызывать разные функции, в зависимости от того, какой вид контроллера видимости видим, вы можете захотеть рассмотреть Key-Value Observing, чтобы получать уведомления, когда изменяется значение для определенных переменных.

Кроме того, вы никогда не хотите инициализировать такой контроллер вида, а затем сразу же установите IBOutlets контроллера вида, так как IBOutlets не инициализируются до тех пор, пока его представление не будет загружено. Вы должны каким-то образом использовать существующий объект контроллера вида.

Надеюсь это поможет.

Существует другой способ сделать это, используя RxSwift:

  1. Добавьте в проект проекты RxSwift и RxCocoa

  2. Измените свой SharingManager :

     import RxSwift class SharingManager { static let sharedInstance = SharingManager() private let _labelUpdate = PublishSubject<String>() let onUpdateLabel: Observable<String>? // any object can subscribe to text change using this observable // call this method whenever you need to change text func triggerLabelUpdate(newValue: String) { _labelUpdate.onNext(newValue) } init() { onUpdateLabel = _labelUpdate.shareReplay(1) } } 
  3. В вашем ViewController вы можете подписаться на обновление значения двумя способами:

    а. подписаться на обновления и вручную изменить текст ярлыка

     // add this ivar somewhere in ViewController let disposeBag: DisposeBag() // put this somewhere in viewDidLoad SharingManager.sharedInstance.onUpdateLabel? .observeOn(MainScheduler.instance) // make sure we're on main thread .subscribeNext { [weak self] newValue in // do whatever you need with this string here, like: // self?.myLabel.text = newValue } .addDisposableTo(disposeBag) // for resource management 

    б. связывать обновления непосредственно с UILabel

     // add this ivar somewhere in ViewController let disposeBag: DisposeBag() // put this somewhere in viewDidLoad SharingManager.sharedInstance.onUpdateLabel? .distinctUntilChanged() // only if value has been changed since previous value .observeOn(MainScheduler.instance) // do in main thread .bindTo(myLabel.rx_text) // will setText: for that label when value changed .addDisposableTo(disposeBag) // for resource management 

И не забудьте import RxCocoa в ViewController.

Для запуска события просто вызовите

 SharingManager.sharedInstance.triggerLabelUpdate("whatever string here") 

ЗДЕСЬ вы можете найти пример проекта. Просто pod update и запустите файл рабочей области.

 var item = "initial value" { didSet { //called when item changes print("changed") } willSet { print("about to change") } } item = "p" 

Apple предоставляет следующие типы объявлений:

1. Вычислимые свойства: –

Помимо хранимых свойств, классы, структуры и перечисления могут определять вычисленные значения, которые фактически не сохраняют значение. Вместо этого они предоставляют геттер и дополнительный сеттер для извлечения и установки других свойств и значений косвенно.

 var otherBool:Bool = false public var enable:Bool { get{ print("i can do editional work when setter set value ") return self.enable } set(newValue){ print("i can do editional work when setter set value ") self.otherBool = newValue } } 

2. Вычислимые свойства только для чтения: –

Вычисленное свойство с геттером, но без сеттера, известно как вычислимое свойство только для чтения. Вычислимое свойство только для чтения всегда возвращает значение и может быть доступно через точечный синтаксис, но не может быть установлено на другое значение.

 var volume: Double { return volume } 

3. Наблюдатели за имуществом: –

У вас есть возможность определить одного или обоих этих наблюдателей на свойстве:

willSet вызывается непосредственно перед сохранением значения.
Функция didSet вызывается сразу после сохранения нового значения.

 public var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } didSet { if totalSteps > oldValue { print("Added \(totalSteps - oldValue) steps") } } } 

ПРИМЕЧАНИЕ. – Для получения дополнительной информации посетите профессиональную ссылку https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html.

  • Воспроизведение таблиц Но не показано, если я не щелкнув нигде в ViewController в swift 2.0?
  • Невозможно установить translatesAutoresizingMaskIntoConstraints
  • использование невосстановленного идентификатора FIRMessaging
  • NSFetchRequest с закрытием функции предиката / сортировки
  • Просмотр автоматически получать в iOS
  • Применить визуальный эффект к пикселям изображения в Swift
  • Внедрение виджета комментариев Facebook в приложении iOS
  • Пользовательский Segue в Swift
  • Вход Google не перенаправляется на приложение после разрешения
  • Связывание двух кадров / позиций UIview с использованием Rxswift
  • Swift Modal View Controller с прозрачным фоном
  • Interesting Posts

    Как очистить UITextView … для реального

    NSData из MPMediaItem

    ios Facebook login: com.facebook.sdk: ErrorLoginFailedReason = invalid_client

    Новый iPad: предупреждения о низкой памяти не появляются?

    Недопустимый путь изображения – изображения не найдены

    Как добавить несколько CALayer в видеофайл с помощью AVMutableComposition и CALayers на iOS

    Какая из встроенных аудиоустройств может воспроизводить аудио?

    как сделать это всплывающее расширение более универсальным для применения к любому представлению?

    Xcode: запрос на открытие приложения не выполнен

    Сертификат Push Services не отображается в разделе «Мои сертификаты»

    Изменение анимационного числа UILabel

    Делегировать полноэкранное событие AVPlayer object-c

    Core plot – добавьте OutOfRange для рисования графика, который динамически изменяется с меткой «OL»

    Запретить TextInput фокусироваться при прокрутке на iOS

    Пользовательское обрезка изображения с использованием пути безье

    Давайте будем гением компьютера.