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

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

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

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

【问题讨论】:

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

标签: ios uiview swift ios8


【解决方案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变量的声明

    【讨论】:

      猜你喜欢
      • 2019-05-17
      • 2020-01-02
      • 1970-01-01
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-27
      • 2022-01-13
      相关资源
      最近更新 更多