【问题标题】:How do I assign an IBOutlet a value using an Initializer?如何使用 Initializer 为 IBOutlet 赋值?
【发布时间】:2015-04-12 20:01:40
【问题描述】:

我觉得应该工作的东西有困难,我想知道关于初始化 IBOutlets 的值是否有一些我不理解的事情。

所以我创建了一个包含三个 IBOutlets 的类。然后我为这些出口变量创建了初始化程序。当我创建一个类的新实例并将硬编码值传递给它时,我得到 nil 作为回报。

所以我已经 println()'ed 传入的 settingLabel 值,以确保传入的参数确实带有一个值,它按预期返回为 "hello"。然后我尝试将值分配给 settingsLabel.text,但是当我调用 println(settingsLabel.text) 时返回为 nil

(线程 1:EXV_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0))

我的问题是:

我在这里缺少什么和/或如何使用初始化程序为 IBOutlet 分配值?

这是我对初始化程序的调用:

let cell = SettingCell(settingLabel: "hello", settingSwitch: true, timeSetting: 3)

这是我的 SettingCell.swift 类:

class SettingCell: UITableViewCell {

    @IBOutlet weak var settingsLabel: UILabel!
    @IBOutlet weak var settingsSwitch: UISwitch!
    @IBOutlet weak var timeSetting: UILabel!

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }

    init(settingLabel: String, settingSwitch: Bool, timeSetting: NSNumber) {

        println(settingLabel) // returns hello <--------------------

        super.init(style: .Default, reuseIdentifier: "SwitchSettingCell")
        settingsLabel.text = settingLabel
        self.settingsSwitch.on = settingSwitch
        self.timeSetting.text = timeSetting.description as String

        println(settingsLabel.text) // returns nil <--------------------

    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    var cellDelegate: SettingCellDelegate?


    @IBAction func handledSwitchChange(sender: UISwitch) {

        self.cellDelegate?.didChangeSwitchState(sender: self, isOn:settingsSwitch!.on)


    }

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

我的故事板:

【问题讨论】:

  • 设置标签不是可选的
  • 我在故障排除期间正在使用可选选项,感谢您指出这一点,我已经测试并更新了帖子以反映当前失败的代码。

标签: swift init iboutlet


【解决方案1】:

IBOutlet 关键字只是告诉 Xcode 视图应该在故事板中可见的一种方式。您可以在情节提要中连接这些出口,这样做会导致变量被实例化并作为情节提要中的子视图添加,而不是在代码中。

在您的代码中,您是以编程方式创建单元格,而不是从情节提要(事实上,如果您尝试从情节提要创建它们,您的应用会崩溃,因为您还没有实现init(coder:))。因此,您的变量没有理由成为“出口”,也没有被初始化。您必须自己初始化它们,将它们添加为子视图和设置约束,全部在代码中。

在您的初始化程序中,您的代码无效,因为您的变量仍然是nil。实际上,在您的编辑中,您删除了可选的链接 ?s,这将导致您的应用程序崩溃,因为变量是强制解包的,但它们是 nil。这与println(settingsLabel.text) 崩溃的原因相同。


编辑:

好的,所以您的问题是您想从情节提要中初始化您的单元格,但您是通过调用自定义初始化程序以编程方式进行的。在tableView(_:cellForRowAtIndexPath:) 中,您可以通过从重用队列中取出一个单元来获取单元:

let cell = tableView.dequeueReusableCellWithIdentifier("SettingsCell", forIndexPath: indexPath) as! SettingCell

(假设您在情节提要中为单元原型指定了标识符“SettingsCell”)

每当从情节提要创建视图时,都会使用视图的 init(coder:) 初始化程序,因此您必须在 SettingCell 子类中提供此实现。单元格出列后,单元格的出口将被初始化并添加为单元格的子视图。

所以在出列单元格后,您可以设置标签和切换:

cell.settingsLabel.text = //...
cell.settingsSwitch.on = //...
cell.timeSetting.text = //...

【讨论】:

  • 我已经更新了我的帖子以显示我的故事板,我确实有来自标签和开关的连接...这是问题吗?
  • 所以,基本上你的意思是,如果我想通过将它们传递到我的 SettingsCell( ) 来创建单元格,我需要在不使用情节提要的情况下以编程方式这样做吗?此外,之前我使用 dequeReusableCellWithIdentifier 创建单元并将其转换为 SettingCell。
  • 是的,您只能以编程方式调用自定义初始化程序。对于表格视图单元格,我强烈反对这样做,并建议您改为让表格视图从情节提要中为您创建它们。我已经编辑了答案以详细说明这一点。
  • 我刚刚阅读了您的编辑。这就是我之前所做的,但我希望能够传递我的 cellForRowAtIndexPath 两种不同类型的单元格,一种带有标签和开关,另一种带有两个标签。这就是我开始初始化过程的原因
  • 在这种情况下,您应该在情节提要中使用不同的重用标识符(例如“SwitchCell”和“LabelCell”)创建两个不同的单元原型,并且每个不同的类都连接了适当的插座。然后,您可以根据tableView(_:cellForRowAtIndexPath:) 中的索引路径有条件地使其中一个或另一个出队。
猜你喜欢
  • 2021-01-30
  • 1970-01-01
  • 2017-02-19
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-19
相关资源
最近更新 更多