Swift弱的懒惰变量不会编译

时间:2016-07-03 16:24:16

标签: swift cocoa lazy-evaluation weak-references

为了证明这个问题,我做了一个香草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外,错误相同。

如果我从声明中删除weaklazy,那就没关系了。但我想将引用计数保存为+1,因为MyCustomClassNSViewController,肯定会一直存在。

任何关于如何使用弱惰性变量的想法?

4 个答案:

答案 0 :(得分:27)

弱而懒惰不能很好地混合。错误消息在解释正在发生的事情时完全没用,但基本上lazyweak彼此不一致:

  • 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
}

}