如何使用 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 中,存储的属性 不能在子类中被覆盖或重新声明。它们只能被继承。
但是,您可以在子类中覆盖 properties
的 getter
和 setter
,以提供额外的验证或功能。参考 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
。从SuperClass
label
拖动到storyBoard在view controller1
现在再次打开SuperClass
一侧和另一侧view controller2
并将插座从SuperClass
连接到view controller2
的storyBoard中的label
。从SuperClass
label
拖动到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 在展开时发现为零