IBDesignable UIButton 子类

Posted

技术标签:

【中文标题】IBDesignable UIButton 子类【英文标题】:IBDesignable UIButton Subclass 【发布时间】:2014-10-28 12:23:44 【问题描述】:

我正在尝试实现一个简单的 。我希望能够从 Interface Builder 为控件的每个状态设置颜色。我知道这可以通过 IBInspectable 关键字来实现。在 state 属性上使用 KVO 时,我遇到了 IB 崩溃的问题。 IBDesignable 调试器在 deinit 上崩溃。有谁知道我如何将 KVO 和 IBDesignable 一起使用?

@IBDesignable
class UIButtonActionButton: UIButton 

    @IBInspectable var defaultColour: UIColor = UIColor.blueColor() 
        didSet 
            self.setNeedsDisplay()
         
    

    @IBInspectable var selectedColour: UIColor = UIColor.blueColor()

    @IBInspectable var disabledColour: UIColor = UIColor.grayColor()

    required init(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self._setup()
    

    override init(frame: CGRect) 
        super.init(frame: frame)
        self._setup()
    


    private func _setup()
        self.addObserver(self, forKeyPath: "state", options: NSKeyValueObservingOptions.New, context: nil)
        self.layer.cornerRadius = 5.0
        self.layer.masksToBounds = true
    

    override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) 
        self.setNeedsDisplay()
    

    override func drawRect(rect: CGRect) 
        super.drawRect(rect)
        let context = UIGraphicsGetCurrentContext()

        if self.highlighted 
            CGContextSetFillColorWithColor(context, selectedColour.CGColor)
            CGContextFillRect(context, self.bounds)
         else if self.state == UIControlState.Disabled 
            CGContextSetFillColorWithColor(context, disabledColour.CGColor)
            CGContextFillRect(context, self.bounds)
         else 
            CGContextSetFillColorWithColor(context, defaultColour.CGColor)
            CGContextFillRect(context, self.bounds)
        
    

    deinit 
        self.removeObserver(self, forKeyPath: "state", context: nil)
    


【问题讨论】:

【参考方案1】:

对于 Xcode 7.2@IBDesignable UIButton Subclass 的通用代码如下所示:

import UIKit

@IBDesignable class MyButton: UIButton 

    //this init fires usually called, when storyboards UI objects created:
    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.setupViews()
    

    //This method is called during programmatic initialisation
    override init(frame: CGRect) 
        super.init(frame: frame)
        setupViews()
    


    func setupViews() 
        //your common setup goes here
    

    //required method to present changes in IB
    override func prepareForInterfaceBuilder() 
        super.prepareForInterfaceBuilder()
        self.setupViews()
    

【讨论】:

我注意到,如果您删除init(frame:) 中的setupViews() 调用,设置在IB 和应用程序中仍然有效。我们是否有理由需要从该初始化中调用设置? @PaulVanWieren 很有趣。我记得,它不起作用。在setupViews() 中设置断点并检查,是谁在调用它:) @PaulVanWieren - 如果在代码中创建视图,则使用 init(frame:) 方法。在故事板和 nib 中创建的视图使用 init(coder:) 方法。如果您不打算在代码中创建视图,则不严格要求具有 init(frame:) 方法,但通常包含它是为了完整性。 为我节省了很多时间和精力 请注意,如果您使用任何@IBInspectable,您只会在“awakeFromNib”中将它们设置在运行时,因此您也需要添加它: override func awakeFromNib() super.awakeFromNib() setupViews( ) 。也许你需要从 init(withDecoder) 中删除 setupViews()???【参考方案2】:

我遇到了类似的问题,问题是 init() 方法在重构我的代码后导致崩溃,它就像一个魅力。也许它会帮助你:

#if !TARGET_INTERFACE_BUILDER
required init(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    self._setup()

#endif

override func prepareForInterfaceBuilder() 
    self._setup()

【讨论】:

感谢丹尼尔的提示。我尝试了上述方法,现在它抱怨我的 IBInspectable 属性不符合键值编码。所以我只在运行时使用宏来添加/删除观察者。接受 MACRO 提示的这个答案。

以上是关于IBDesignable UIButton 子类的主要内容,如果未能解决你的问题,请参考以下文章

Swift UIButton 子类未显示在设备或模拟器上

无法将自定义 IBDesignable 类链接到情节提要上的 UIButton

Interface Builder PREVIEW使用IBDesignable和核心图形(drawrect)?

如何使用 @IBDesignable 和 @IBInspectable 制作 uitextfield 的自定义子类并在那里我可以从左侧设置占位符填充

IBDesignable UIViewController

IBDesignable UIViewController