2017-01-10 59 views
0

我有一个SettingsViewController并创建了一个结构来定义每个设置所需的信息。为什么这个闭包没有我期望的论点?

///Represents a list of the options needed to populate a `SettingsTableViewCell` 
public struct Setting { 
    ///The image to use for the icon 
    var imageName : String 

    ///The text to display as the title of the setting 
    var title : String 

    ///Called when the switch is tapped. If no closure is supplied, the switch is hidden 
    var switchCallback: ((_ status: Bool)->())? 
} 

视图控制器保留这些设置的数组,以便稍后在表视图中使用。一个的例子下面提供:

let options : [Setting] = 
[ 
    Setting(imageName: "notifications", title: "Bump Notifications") {updateNotificationSetting($0)}, 
    ... 
] 

然而,当我尝试编译,我提出与错误:

Cannot convert value of type '(SettingsViewController) -> (Bool) ->()' to expected argument type '((Bool) ->())?' 

有人能解释其中(SettingsViewController)是从哪里来的吗?如果可以的话,我需要改变以修复它吗?


对于SSCCE,见下图:

import UIKit 

///Represents a list of the options needed to populate a `SettingsTableViewCell` 
public struct Setting { 
    ///The image to use for the icon 
    var imageName : String 

    ///The text to display as the title of the setting 
    var title : String 

    ///Called when the switch is tapped. If no closure is supplied, the switch is hidden 
    var switchCallback: ((_ status: Bool)->())? 
} 



@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate { 

    var window: UIWindow? 

    let options : [Setting] = 
    [ 
     //Error is on the following line 
     Setting(imageName: "notifications", title: "Bump Notifications") {isOn in updateSetting(isOn)}, 
    ] 

    func updateSetting(isOn : Bool) { 

    } 

} 
+0

在你的闭包初始化的某处。 – Sulthan

+0

闭包中没有明确的'self'(见上面),但我认为'updateNotifications($ 0)'前面有一个隐含的'self'。有关如何在这种情况下调用该函数的任何建议,请? –

+0

不相关,但在Swift 3中,回调闭包中的所有参数标签已被删除。回调签名 - 正如错误信息中显示的 - 只是'(Bool) - >()','status'完全不用。 – vadian

回答

2

的封盖,你Setting初始化器捕捉self。但是,Swift中的self仅在初始化对象的所有属性后才可用,也就是let options初始化后。打破圈子

一种方法是使用属性的延迟初始化:

public struct Setting { 
    var imageName : String 
    var title : String 
    var switchCallback: ((_ status: Bool)->())? 
} 

class MyClass { 
    lazy var options: [Setting] = [ 
     Setting(imageName: "x", title: "X") { [unowned self] in self.updateSetting(isOn: $0)} 
    ] 

    func updateSetting(isOn : Bool) {} 
} 

注意明确的类型: [Setting]当前需要报关。

请注意,您需要使用[unowned self][weak self]来中断发布周期(感谢@rob评论)。

+0

@Rob在我的测试中没有引用循环,对象被释放,但我可能会把'[无主自我]'只是为了确保。 – Sulthan

+0

@Rob哦,是的,你是对的! – Sulthan

0

But (a) you have to have an explicit reference to self in the closure (e.g. self.updateNotificationSetting); and (b) to do that, you can only do that if you make it lazy var rather than let (allowing it to now resolve self).

虽然我是不是能够得到与关键字lazy var这方面的工作,这确实给我,我需要解决的问题的信息。我结束了基本上使自己的懒惰的变种,只是在我使用该数组之前实例化它:

private var options : [Setting]! 


... 

if options == nil { 
     options = [ 
      Setting(imageName: "notifications", title: "Bump Notifications") {isOn in self.updateNotificationSetting(isOn: isOn)}, 
      Setting(imageName: "automatic_check_in", title: "Automatic Check In") {isOn in self.updateAutomaticCheckInSetting(isOn:isOn)}, 
      Setting(imageName: "logout", title: "Logout", switchCallback:nil) 
     ] 
    } 
+0

我建议对'self'的'weak'或'unownned'引用,例如'设置(imageName:“automatic_check_in”,标题:“自动检入”){[weak self] isOn in self ?.updateAutomaticCheckInSetting(isOn:isOn)}'。 – Rob

相关问题