- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我的应用程序中有一个单例类,根据 this blog post 中的一行单例(带有私有(private) init()
)声明。 .具体来说,它看起来像这样:
@objc class Singleton {
static let Singleton sharedInstance = Singleton()
@objc dynamic var aProperty = false
private init() {
}
}
我想将 aProperty
的状态绑定(bind)到菜单项是否隐藏。
以下是我执行此操作所遵循的步骤:
转到 Interface Builder 中的对象库,然后将通用“对象”添加到我的应用程序场景。在身份检查器中,将“类”配置为 Singleton
。
通过按住 Ctrl 从 Interface Builder 中的单例对象拖动到我的 App Delegate 代码,在我的 App Delegate 中创建一个引用导出。它最终看起来像这样:
@IBOutlet weak var singleton: Singleton!
aProperty
在“模型关键路径”下。不幸的是,这不起作用:更改属性对相关菜单项没有影响。
问题似乎是,尽管将 init()
声明为私有(private),但 Interface Builder 正在设法创建我的单例的另一个实例。为了证明这一点,我将 NSLog("singleton init")
添加到私有(private) init()
方法,并将以下代码添加到 applicationDidFinishLaunching()
在我的应用委托(delegate)中:
NSLog("sharedInstance = \(Singleton.sharedInstance) singleton = \(singleton)")
当我运行该应用程序时,日志中会输出以下内容:
singleton init
singleton init
sharedInstance = <MyModule.Singleton: 0x600000c616b0> singleton = Optional(<MyModule.Singleton: 0x600000c07330>)
因此,确实存在两种不同的情况。我还在我的应用程序委托(delegate)中的其他地方添加了这段代码:
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 中声明一个单例类并将其与 Interface Builder 连接起来以避免它被实例化两次?
如果这不可能,我还能如何解决将全局属性绑定(bind)到 Interface Builder 中的控件的问题?
我希望描述足够详细,但如果有人觉得 MCVE 是必要的,请发表评论,我会创建一个并上传到 GitHub。
最佳答案
我只是想通过说明单例不应该用于共享全局状态来开始我的回答。虽然它们在开始时看起来更容易使用,但它们往往会在以后产生很多麻烦,因为它们几乎可以从任何地方更改,有时会使您的程序变得不可预测。
话虽这么说,实现您的需求并非不可能,但需要一点仪式感:
@objc class Singleton: NSObject {
// using this class behind the scenes, this is the actual singleton
class SingletonStorage: NSObject {
@objc dynamic var aProperty = false
}
private static var storage = SingletonStorage()
// making sure all instances use the same storage, regardless how
// they were created
@objc dynamic var storage = Singleton.storage
// we need to tell to KVO which changes in related properties affect
// the ones we're interested into
override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
switch key {
case "aProperty":
return ["storage.aProperty"]
default: return super.keyPathsForValuesAffectingValue(forKey: key)
}
}
// and simply convert it to a computed property
@objc dynamic var aProperty: Bool {
get { return Singleton.storage.aProperty }
set { Singleton.storage.aProperty = newValue }
}
}
关于swift - Swift 和 Interface Builder 中的单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54400618/
我最近购买了《C 编程语言》并尝试了 Ex 1-8这是代码 #include #include #include /* * */ int main() { int nl,nt,nb;
早上好!我有一个变量“var”,可能为 0。我检查该变量是否为空,如果不是,我将该变量保存在 php session 中,然后调用另一个页面。在这个新页面中,我检查我创建的 session 是否为空,
我正在努力完成 Learn Python the Hard Way ex.25,但我无法理解某些事情。这是脚本: def break_words(stuff): """this functio
我是一名优秀的程序员,十分优秀!