初始化需要“self”作为参数的 Swift 属性

Posted

技术标签:

【中文标题】初始化需要“self”作为参数的 Swift 属性【英文标题】:Initializing Swift properties that require "self" as an argument 【发布时间】:2014-08-05 22:15:45 【问题描述】:

我有一个 Swift 类,我希望它看起来像这样:

class UpdateManager 
  let timer: NSTimer

  init() 
    timer = NSTimer(timeInterval: 600, target: self, selector: "check", userInfo: nil, repeats: true)
  

  func check() 
    // Do some stuff
  

但是,Swift 不喜欢我将 self 传递给 NSTimer 初始化程序的事实。我在这里打破了一些模式吗?应该如何完成这样的初始化?

【问题讨论】:

【参考方案1】:

您已找到Implicitly Unwrapped Optional 的主要用例。

在初始化timer之前,您需要从init访问self。 否则,timer 应该永远为零,因此您不必在init 之外检查它。

所以,你应该声明let timer: NSTimer!

【讨论】:

这很棒。当您回答时,我已经知道如何将隐式解包选项与var 一起使用,但不知道它们与let 兼容。谢谢! 这是一个很好的问题,坦率地说,我很惊讶它还没有被问到!很高兴看到 IUO 被用于其真正目的,而不是在导入 Obj-C API 时自动撒在各处......【参考方案2】:

Swift 2 可能改变了工作方式。我正在使用如下代码:

@objc class Test : NSObject 
    var timer : NSTimer!
    init text() 
        super.init()
        timer = NSTimer(timeInterval: 1.0, target: self, selector: "timerFired:", userInfo: nil, repeats: true)
        NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
    

需要@objc 声明和 NSObject 子类。 另外 timer 需要是一个 var,而不是 let。

【讨论】:

【参考方案3】:

除了隐式展开的可选选项之外,我发现要使代码正常工作,我需要继承 NSObject 并将计时器添加到当前运行循环中。

class UpdateManager:NSObject 
    let timer: NSTimer!

    override init() 
        super.init()
        timer = NSTimer(timeInterval: 600, target: self, selector: "check", userInfo: nil, repeats: true)
        NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSDefaultRunLoopMode)
    


    func check() 
        // Do some stuff

    

基于 cmets 更新代码 - 感谢 jtbandes 和 Caroline

class UpdateManager 
    let timer: NSTimer!

   init() 

        timer = NSTimer.scheduledTimerWithTimeInterval(600,
            target: self,
            selector: "check",
            userInfo: nil,
            repeats: true)
    


   @objc func check() 
        // Do some stuff

    

【讨论】:

您可能想改用NSTimer.scheduledTimerWithTimeInterval(_:target:selector:userInfo:repeats:) 这消除了将计时器添加到运行循环的需要,但如果 NSObject 没有被子类化,则应用程序崩溃并显示以下消息:“不实现 methodSignatureForSelector: -- 前面的麻烦” 你可以像@objc func check () 一样将@objc属性添加到函数中,而不是继承NSObject 感谢@Caroline,它有效,我现在在文档中看到它的详细说明:“当您使用 Objective-C 类时,此属性 [@objc] 也很有用使用选择器来实现目标动作设计模式——例如,NSTimer 或 UIButton。”值得一提的是,使用 dynamic 关键字也可以阻止应用程序崩溃,尽管我们应该使用 @objc

以上是关于初始化需要“self”作为参数的 Swift 属性的主要内容,如果未能解决你的问题,请参考以下文章

如何使用属性作为 FetchRequest 谓词的参数

swift 类型系统 Self self Type

Swift:错误将 self 作为 inout 参数传递

'#selector'的参数不是指'@objc'方法,属性或初始值设定项

在 swift 中使用协议作为数组类型和函数参数

Swift 1.2 中的 @noescape 属性