如何使用 IBOutlet 子类化变量?

Posted

技术标签:

【中文标题】如何使用 IBOutlet 子类化变量?【英文标题】:How do I subclass a variable with an IBOutlet? 【发布时间】:2014-08-01 21:03:30 【问题描述】:

我的特定班级的所有后代都有一个UILabel 实例变量。所以在我的父类中,我有var label: UILabel。我也想把它放在子类中,但是作为IBOutlet。我该怎么做?

我添加了同名的IBOutlet,并在两个变量声明中添加了weak。但是我收到一个关于“不能用存储的属性覆盖”的错误。

我应该怎么做?是否可以不必实例化超类的版本,因为我只希望它用于子类化?

【问题讨论】:

不清楚您为什么要这样做。为什么不在子类中有不同的实例变量?您真正想要解决的问题是什么? @matt 我有一个正在出列的视图控制器,它可以是两种不同类型的相似视图控制器之一。我想使用多态性来使用它们的超类来执行操作。有没有更好的方法来做到这一点? @DougSmith 编辑的答案看看 @DougSmith 你可以覆盖getter and setter 并且可以将出口连接到子类 从您的“解释”中我仍然看不到为什么这些需要是 same 实例变量。您只需要一个指针,它对超类是通用的,然后它指向 A 类中的一个变量和 B 类中的另一个变量。 【参考方案1】:

通过这样做,您是 re-declaring 子类中的 label 属性。 IBOutlet 只是用于使用 Interface Builder 的编译器概念。

在 Swift 中,存储的属性 不能在子类中被覆盖或重新声明。它们只能被继承。

但是,您可以在子类中覆盖 propertiesgettersetter,以提供额外的验证或功能。参考 Swift 指南:override getter setter

您需要使用IBOutlet在超类中声明您的属性。

或者你可以在你的子类中创建一个不同的属性。同样,如果您将您的属性连接到一个子类(超类可能有其他)并且您没有将此实现提供给您的超类的其他子类,也没有任何意义。

编辑:如果您将情节提要中的Subclasses 名称赋予不同的视图控制器,您还可以将label 出口设置为情节提要中SuperClass 的两个不同viewControllers

只要定义

 class SuperClass
     @IBOutlet weak var label: UILabel! = nil

 

SubClass1 代表view controller1 在故事板中源自SuperClass SubClass2 在源自SuperClass 的情节提要中代表另一个view controller2

转到Assistant Editor并打开SuperClass一侧和另一侧view controller1并将插座从SuperClass连接到view controller1的storyBoard中的label。从SuperClasslabel拖动到storyBoard在view controller1

现在再次打开SuperClass一侧和另一侧view controller2并将插座从SuperClass连接到view controller2的storyBoard中的label。从SuperClasslabel拖动到view controller2的storyBoard中

如果你点击SuperClass outlet,你会看到两个标签连接到不同的 viewControllers

【讨论】:

有趣。正在调查。 我根本听不懂英语......了解这里发生了什么的人可以修改这个答案。谢谢 如果父类是通用的,这个解决方案似乎不起作用。请确认一下好吗?【参考方案2】:

只需在超类中添加IBOutlet 修饰符即可。

【讨论】:

我如何将视图链接到 IBOutlet 变量? 与没有子类化的方式相同。只需将您的 ViewController 设置为使用您的子类并控制并拖动组件即可。 如果我将它包含在子类中,这样我就可以控制+拖动组件,我会得到同样的错误。 这仅在您有权访问超类时才有效...【参考方案3】:

同意简短的回答很简单:

“只需​​在超类中添加@IBOutlet 修饰符即可。”

但请注意:如果您要公开通过框架(使用 Carthage)定义 @IBOutlet 的 ViewController,则需要将 public 属性添加到变量定义中。 编辑:改为使用 open 访问关键字`。

假设您有一个视图控制器 CustomViewController 子类化 UITableViewController,您将在 Carthage 交付的框架中构建它。消费者应用程序应该可以访问的所有内容都应该标记为public

public class CustomViewController: UIViewController 

    override public func viewDidLoad() 
        super.viewDidLoad()
    

@IBOutlet public var myBackgroundView: UIView!
@IBOutlet public weak var myLabel: UILabel!

这种方法的好处(我完全支持这个用例)是您可以在超类的 Interface Builder 中进行 IBOutlet 映射,然后切换场景到子类,同时保留所有映射。

例如:SubclassedCustomViewController

import UIKit
import mymodule

class SubclassedCustomViewController: CustomViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
        myBackgroundView.backgroundColor = UIColor.blueColor()
        myLabel.text = "My special subclass text"
    

【讨论】:

【参考方案4】:

我意识到这个问题是不久前发布的,但由于我只是在同一个问题上苦苦挣扎并最终想出了一个解决方案,我想我还是会发布我的发现......

我理解问题如下(至少这是我解决的问题):

如何让 A 类从 B 类继承,每个类都有自己的 XIB 文件和一些常见的 IBOutlet 属性? 目标是能够让超类处理相关的操作到其子类共有的 IBOutlets,同时仍然能够使用 Interface Builder 为子类设计接口。*

为此:

在超类中从 超类的XIB文件 从子类的 XIB 建立子类中的 IBOutlet 连接 文件,具有与您需要继承的超类中相同的 IBOutlet 属性名称。 删除子类中IBOutlet变量的声明

【讨论】:

以上是关于如何使用 IBOutlet 子类化变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Xcode 5 中让两个按钮转到同一个 IBOutlet?

重用带有通过 IBOutlet 连接到超类的 uitableview 的 xib:如何更好地为某些子类添加带有按钮的工具栏?

Swift 中的 UIView 子类:IBOutlet 在展开时发现为零

使用插座子类化主视图控制器

UITableView 的自定义初始化连接为 IBOutlet [关闭]

在类中子类化变量