Фон
У меня есть одноэлементный класс в моем приложении, объявленный в соответствии с однострочным синглтоном (с личным init()
) в этом сообщении в блоге .В частности, это выглядит так:
@objc class Singleton {
static let Singleton sharedInstance = Singleton()
@objc dynamic var aProperty = false
private init() {
}
}
Я бы хотел связать состояние aProperty
с тем, скрыт ли пункт меню.
Как я пытался решить проблему
Вот шаги, которые я выполнил для этого:
Перейдите в Библиотеку объектов в Интерфейсном Разработчике и добавьте универсальный «Объект» в мою сцену Приложения.В инспекторе удостоверений настройте «Класс» на Singleton
.
Создайте ссылочную точку в моем делегате приложения путем перетаскивания Ctrl из одноэлементного объекта в Интерфейсном конструкторе в код моего делегата приложения,В итоге это выглядит так:
@IBOutlet weak var singleton: Singleton!
Перейдите в инспектор привязок для пункта меню, выберите «Скрытый» в разделе «Доступность», установите флажок «Привязать к», выберите «Синглтон» в поле со списком перед ним и введите
aProperty
в разделе «Ключ модели».Путь ".
Проблема
К сожалению, это не работает: изменение свойства не влияет на данный пункт меню.
Расследование причины
Проблема заключается в том, что, несмотря на объявление init()
как частного, Interface Builder удается создать еще один экземпляр моего синглтона.Чтобы доказать это, я добавил NSLog("singleton init")
в приватный метод init()
, а также следующий код в applicationDidFinishLaunching()
в моем делегате приложения:
NSLog("sharedInstance = \(Singleton.sharedInstance) singleton = \(singleton)")
Когда я запускаю приложение, это выводится вжурналы:
singleton init
singleton init
sharedInstance = <MyModule.Singleton: 0x600000c616b0> singleton = Optional(<MyModule.Singleton: 0x600000c07330>)
Следовательно, действительно есть два разных случая.Я также добавил этот код где-то еще в моем делегате приложения:
NSLog("aProperty: [\(singleton!.aProperty),\(String(describing:singleton!.value(forKey: "aProperty"))),\(Singleton.sharedInstance.singleton),\(String(describing:Singleton.sharedInstance.value(forKey: "aProperty")))] hidden: \(myMenuItem.isHidden)")
В какой-то момент это приводит к следующему выводу:
aProperty: [false, Optional (0), true, Optional(1)] hidden: false
Очевидно, что, будучи единичным, все значения должны совпадать, но singleton
производит один вывод, а Singleton.sharedInstance
производит другой.Как можно видеть, вызовы value(forKey:)
соответствуют их соответствующим объектам, поэтому KVC не должен быть проблемой.
Вопрос
Как мне объявить одноэлементный класс в Swift и wireэто с Интерфейсным Разработчиком, чтобы избежать его создания дважды?
Если это невозможно, как еще я бы решил проблему связывания глобального свойства с элементом управления в Интерфейсном Разработчике?
Нужен ли MCVE?
Надеюсь, описание было достаточно подробным, но если кто-то считает, что MCVE необходим, оставьте комментарий, и я его создам, и выложу на GitHub.