如何初始化一个UIButton的子类?

88

我试图在Swift中将一个双精度浮点数添加到UIButton的子类中。我尝试了各种初始化和获取和设置选项,但是我无法让它正常工作。

于是我从这个开始:

class CVSTButton : UIButton {
    var cvstPosition: Double

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

        super.init(coder: aDecoder)
    }
}

然后我尝试了:

class CVSTButton : UIButton {
    var cvstPosition: Double {
        get {
            return self.cvstPosition
        }
        set {
            self.cvstPosition = newValue
        }

    }

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

这里有什么问题?

4个回答

273

使用Swift 3,您可以根据需要选择以下七个代码片段之一来解决问题。


1. 使用自定义初始化程序创建UIButton子类

此解决方案允许您创建具有适当属性值的UIButton子类实例。使用此解决方案,您只能通过编程方式创建UIButton子类实例。

import UIKit

class CustomButton: UIButton {

    var myValue: Int

    required init(value: Int = 0) {
        // set myValue before super.init is called
        self.myValue = value

        super.init(frame: .zero)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

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

}

使用方法:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(value: 0)
        // let button = CustomButton() // also works
        button.setTitle("Hello", for: .normal)

        // auto layout
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        print(button.myValue) // prints 0
    }

}

2. 使用便利初始化方法创建您的UIButton子类

这个解决方案可以让您创建具有适当属性值的UIButton子类实例。通过这种方法,您只能以编程方式创建UIButton子类的实例。


import UIKit

class CustomButton: UIButton {

    var myValue: Int

    convenience init(squareOf value: Int) {
        self.init(value: value * value)
    }

    required init(value: Int = 0) {
        // set myValue before super.init is called
        self.myValue = value

        super.init(frame: .zero)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

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

}

使用方法:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(squareOf: 10)
        // let button = CustomButton(value: 100) // also works
        button.setTitle("Hello", for: .normal)

        // auto layout
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        print(button.myValue) // prints 100
    }

}

3. 使用init(frame: CGRect)初始化器创建你的UIButton子类

使用这种解决方案,你只能通过编程方式创建你的UIButton子类的实例。


import UIKit

class CustomButton: UIButton {

    var myValue: Int

    override init(frame: CGRect) {
        // set myValue before super.init is called
        self.myValue = 0

        super.init(frame: frame)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

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

}

使用方法:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let button = CustomButton(frame: .zero)
        //let button = CustomButton() // also works
        button.setTitle("Hello", for: .normal)

        // auto layout
        button.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(button)
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

        print(button.myValue) // prints 0
    }

}

4. 使用init?(coder aDecoder: NSCoder)初始化器来创建自己的UIButton子类

采用这种方法,你可以在Storyboard中创建你的UIButton子类实例。

import UIKit

class CustomButton: UIButton {

    var myValue: Int

    required init?(coder aDecoder: NSCoder) {
        // set myValue before super.init is called
        self.myValue = 0

        super.init(coder: aDecoder)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

}

使用方法:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var button: CustomButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        print(button.myValue) // prints 0
    }

}

5. 使用init(frame: CGRect)init?(coder aDecoder: NSCoder) 初始化方法创建你的UIButton子类

通过这种解决方案,你可以通过编写代码或从Storyboard中创建实例来使用你的UIButton子类。

import UIKit

class CustomButton: UIButton {

    var myValue: Int

    override init(frame: CGRect) {
        // set myValue before super.init is called
        self.myValue = 0

        super.init(frame: frame)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

    required init?(coder aDecoder: NSCoder) {
        // set myValue before super.init is called
        self.myValue = 0

        super.init(coder: aDecoder)

        // set other operations after super.init if required
        backgroundColor = .red
    }

}

6. 创建一个UIButton子类,为你的属性设置一个默认属性值

除了前面提到的解决方案外,你还可以在初始化器之外给属性赋一个初始值。


import UIKit

class CustomButton: UIButton {

    var myValue: Int = 0

    override init(frame: CGRect) {
        super.init(frame: frame)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

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

        // set other operations after super.init if required
        backgroundColor = .red
    }

}

7. 使用可选类型创建UIButton的子类,并设置属性为可选类型

如果您不想或不能在创建按钮时为属性设置默认值,则必须将属性类型设置为可选类型。


import UIKit

class CustomButton: UIButton {

    var myValue: Int? = nil

    override init(frame: CGRect) {
        super.init(frame: frame)

        // set other operations after super.init, if required
        backgroundColor = .red
    }

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

        // set other operations after super.init if required
        backgroundColor = .red
    }

}

38
我喜欢你提供每个代码片段使用场景的情况。非常出色的回答——希望更多问题都像这样得到回答。 - Sami
如果按钮是一个outlet,如何调用convenience init()? - Mamta
在片段 3 的用法部分中,使用帧作为初始化器,最好使用类似于 CustomButton(frame: CGRect(x: 100, y: 300, width: 200, height: 50)) 而不是 CustomButton(frame: .zero) 和自动布局,这样会更清晰。 - paulo62

12

您需要两个要素 -- (1) cvstPosition需要一个初始值,可以在声明中或在调用super.init()之前的init中设置。(2) 添加了fatalError的调用是为了防止您忘记实现初始化程序-- 它基本上是有意的崩溃。删除它!

在声明中设置初始值,就不需要init

class CVSTButton : UIButton {
    var cvstPosition: Double = 0
}

或在初始化程序中设置初始值:

class CVSTButton : UIButton {
    var cvstPosition: Double

    required init(coder aDecoder: NSCoder) {
        cvstPosition = 0

        super.init(coder: aDecoder)
    }
}

啊,太好了,我只需要声明并给变量一个初始值! - Alexander Schutte
在Swift 2.2中,init后面需要加上一个问号,因此代码应该是required init?(coder aDecoder: NSCoder) { - Dan Rosenstark

8

Swift >= 2.2:

自这个版本开始,继承UIButton将使您的按钮具有.custom类型。

Swift 2:

convenience init(type buttonType: UIButtonType) {
    super.init(frame: CGRectZero)

    // this button be automatically .Custom
}

Swift:

override class func buttonWithType(buttonType: UIButtonType) -> AnyObject {
    let button = super.buttonWithType(buttonType) as! UIButton
    // your default code
    return button
}

你想在这里插入“public”。即:override public class func - u2Fan
当然不是。公共是项目之间的范围。 - dimpiax
Re "your subclass becomes with type .Custom default.": 这句话几乎无法理解。你能修复一下吗?(但不要加上“编辑:”、“更新:”或类似的内容——答案应当看起来像今天写的一样。) - Peter Mortensen

4

注意:我在Xcode 8.3.3中使用Swift 3

当需要向UIButton添加自定义属性和方法时,这是我一直在使用的简单易行的解决方法:

class CVSTButton: UIButton {

    var cvstPosition: Double

    static func button(withCVSTPosition cvstPosition: Double) -> CVSTButton {

        let button = CVSTButton(type: .detailDisclosure) // You may adjust the initializer used to suit your needs.

        button.cvstPosition = cvstPosition // Then you can simply set the the properties (which are passed as arguments to the factor/class method)

        return button

    }

}

使用它:

let cvstButton = CVSTButton.button(withCVSTPosition: 2.0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接