为了证明这个问题,我做了一个香草Cocoa项目。这是AppDelegate.swift
:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
weak lazy var isGood : NSNumber? = {
return true
}()
func doSomething() {
let result = isGood!
}
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
Xcode给出了这个:
unkown:0:错误:无法转换“NSNumber”类型的返回表达式(又名'可选')返回类型'NSNumber?'
unkown:0:无法分配“NSNumber”类型的值?输入'NSNumber ??'
unkown:0:无法分配“NSNumber”类型的值?输入'NSNumber ??'
在我的实际项目中,它是MyCustomClass
的另一个对象(而不是NSNumber)。除类型为MyCustomClass
外,错误相同。
如果我从声明中删除weak
或lazy
,那就没关系了。但我想将引用计数保存为+1,因为MyCustomClass
是NSViewController
,肯定会一直存在。
任何关于如何使用弱惰性变量的想法?
答案 0 :(得分:27)
弱而懒惰不能很好地混合。错误消息在解释正在发生的事情时完全没用,但基本上lazy
和weak
彼此不一致:
lazy
告诉Swift,您不希望在第一次访问变量时创建变量,但是一旦创建变量,您希望将其保留为无限期以供将来参考,而weak
告诉Swift你不希望你的变量成为保持你的变量被解除分配的最后一个链接,这对于"无限期保持" lazy
变量的目标。您可以通过模仿lazy
来解决此问题,如下所示:
class Foo {
weak var isGoodCache : NSNumber?
private var makeIsGood : NSNumber {
isGoodCache = true
return isGoodCache!
}
var isGood:NSNumber? {
return isGoodCache ?? makeIsGood
}
}
答案 1 :(得分:7)
懒惰和弱不兼容的原因是每次使用都会创建一个新实例,除非你有另一个拥有强引用的地方。如果您有另一个地方可以保留强引用,那么您不需要您的类成员成为创建实例的成员。
假设我们有:
weak lazy var myVariable: MyClass? = createMyClassInstance()
当你第一次使用它时,假设你只是在某个函数调用中引用它......
myFunction(myVariable)
在下一行,myVariable再次为空。
为什么?因为,一旦myFunction完成,就不再有对myVariable的引用了,因为它很弱,所以相应的对象超出了范围而消失了。
该惰性弱变量与任何函数调用结果之间没有区别。所以,你的变量也可以是一个函数或一个计算变量(这会让任何看你代码的人都更清楚。)
答案 2 :(得分:1)
尝试使用弱计算属性......
import Foundation
class C {
weak var d : NSDate? {
return NSDate()
}
}
let c = C()
print(NSDate())
sleep(1)
print(c.d)
给你想要的行为(如果我理解你的问题: - ))
2016-07-03 16:49:04 +0000
Optional(2016-07-03 16:49:05 +0000)
如果必须只初始化一次,那么
import Foundation
class C {
weak var d : NSDate? {
return d0
}
lazy var d0: NSDate? = {
return NSDate()
}()
}
let c = C()
print(NSDate())
sleep(1)
print(c.d)
sleep(1)
print(c.d)
它可以为您提供所需的
2016-07-03 16:57:24 +0000
Optional(2016-07-03 16:57:25 +0000)
Optional(2016-07-03 16:57:25 +0000)
答案 3 :(得分:0)
参考文献的创建者无需负责保留参考文献。我有一些课程可以有意识地保留自己,并通过释放他们对自我的强烈提及来自行决定什么时候。
我使用另一个类作为这样的工厂。有时我必须调整构造函数的参数,因此这个泛型类更像是模板而不是实际的实现。但是当它们存在时,工厂被设计为返回已经存在的实例。
class Factory<T> {
private weak var refI: T?
var ref: T {
if refI != nil {
return refI
}
let r = T()
refI = r
return r
}
}