首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Swift子类UIView

Swift子类UIView
EN

Stack Overflow用户
提问于 2014-11-21 16:18:44
回答 6查看 77K关注 0票数 98

我想要子类UIView,并显示一个类似登录的视图。这是我在Objective-C中创建的,但现在我想将它移植到Swift。我不使用故事板,所以我所有的UI都是用代码创建的。

但是第一个问题是我必须实现initWithCoder。我给了它一个默认的实现,因为它不会被调用。现在,当我运行程序时,它崩溃了,因为我还必须实现initWithFrame。现在我得到了这个:

代码语言:javascript
复制
override init() {
    super.init()
    println("Default init")
}

override init(frame: CGRect) {
    super.init(frame: frame)
    println("Frame init")
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    println("Coder init")
}

我的问题是我应该在哪里创建我的文本字段等。如果我从来没有实现过框架和编码器,我怎么“隐藏”它呢?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2014-11-21 16:39:10

我通常会做这样的事情,有点冗长。

代码语言:javascript
复制
class MyView: UIView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        addBehavior()
    }

    convenience init() {
        self.init(frame: CGRect.zero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("This class does not support NSCoding")
    }

    func addBehavior() {
        print("Add all the behavior here")
    }
}



let u = MyView(frame: CGRect.zero)
let v = MyView()

(编辑:我已经对我的答案进行了编辑,以便初始化器之间的关系更加清晰)

票数 179
EN

Stack Overflow用户

发布于 2016-11-07 00:47:28

这更简单。

代码语言:javascript
复制
override init (frame : CGRect) {
    super.init(frame : frame)
    // Do what you want.
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}
票数 18
EN

Stack Overflow用户

发布于 2017-01-30 11:49:15

自定义UIView子类示例

我通常不使用故事板或nib来创建iOS应用程序。我将分享我学到的一些技巧来回答你的问题。

隐藏不需要的init方法

我的第一个建议是声明一个基本的UIView来隐藏不需要的初始化器。我已经在my answer to "How to Hide Storyboard and Nib Specific Initializers in UI Subclasses"中详细讨论过这种方法。注意:这种方法假设你不会在故事板或nibs中使用BaseView或它的后代,因为它会故意导致应用程序崩溃。

代码语言:javascript
复制
class BaseView: UIView {

    // This initializer hides init(frame:) from subclasses
    init() {
        super.init(frame: CGRect.zero)
    }

    // This attribute hides `init(coder:)` from subclasses
    @available(*, unavailable)
    required init?(coder aDecoder: NSCoder) {
        fatalError("NSCoding not supported")
    }
}

您的自定义UIView子类应该继承自BaseView。它必须在其初始值设定项中调用super.init()。它不需要实现init(coder:)。下面的示例演示了这一点。

添加UITextField

我为在init方法外部引用的子视图创建存储的属性。对于UITextField,我通常会这样做。我更喜欢在subview属性的声明中实例化子视图,如下所示:let textField = UITextField()

除非通过调用addSubview(_:)将UITextField添加到自定义视图的子视图列表中,否则它将不可见。下面的示例演示了这一点。

不带自动布局的程序化布局

除非设置UITextField的大小和位置,否则它将不可见。我经常在layoutSubviews method中进行代码布局(不使用自动布局)。layoutSubviews()在最初和每次发生调整大小事件时都会被调用。这允许根据CustomView的大小调整布局。例如,如果CustomView在各种大小的iPhones和iPads上显示全宽,并针对旋转进行调整,则它需要适应许多初始大小并动态调整大小。

您可以参考layoutSubviews()中的frame.heightframe.width来获取CustomView的维度以供参考。下面的示例演示了这一点。

示例UIView子类

包含不需要实现init?(coder:)的UITextField的自定义UIView子类。

代码语言:javascript
复制
class CustomView: BaseView {

    let textField = UITextField()

    override init() {
        super.init()

        // configure and add textField as subview
        textField.placeholder = "placeholder text"
        textField.font = UIFont.systemFont(ofSize: 12)
        addSubview(textField)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        // Set textField size and position
        textField.frame.size = CGSize(width: frame.width - 20, height: 30)
        textField.frame.origin = CGPoint(x: 10, y: 10)
    }
}

具有自动布局功能的程序化布局

您还可以在代码中使用Auto layout实现布局。因为我不经常这样做,所以我不会给出一个例子。您可以在Stack Overflow和Internet上的其他地方找到在代码中实现自动布局的示例。

程序化布局框架

有一些开源框架可以在代码中实现布局。我感兴趣但没有尝试过的是LayoutKit。它是由LinkedIn开发团队编写的。来自Github存储库:"LinkedIn创建了LayoutKit,因为我们发现自动布局对于可滚动视图中的复杂视图层次结构的性能不够好。“

为什么要把fatalError放在init(coder:)

在创建永远不会在情节提要或nib中使用的UIView子类时,您可能会引入具有不同参数和初始化要求的初始化器,而这些参数和初始化要求无法由init(coder:)方法调用。如果您没有使用fatalError初始化(编码器:)失败,如果意外地在故事板/nib中使用,它可能会导致非常令人困惑的问题。fatalError断言这些意图。

代码语言:javascript
复制
required init?(coder aDecoder: NSCoder) {
    fatalError("NSCoding not supported")
}

如果你想在创建子类时运行一些代码,而不管它是在代码中创建的,还是在情节串连板/nib中创建的,那么你可以这样做(基于Jeff Gu Kang’s answer)。

代码语言:javascript
复制
class CustomView: UIView {
    override init (frame: CGRect) {
        super.init(frame: frame)
        initCommon()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        initCommon()
    }

    func initCommon() {
        // Your custom initialization code
    }
}
票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27056864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档