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 子类的主要内容,如果未能解决你的问题,请参考以下文章
无法将自定义 IBDesignable 类链接到情节提要上的 UIButton
Interface Builder PREVIEW使用IBDesignable和核心图形(drawrect)?
如何使用 @IBDesignable 和 @IBInspectable 制作 uitextfield 的自定义子类并在那里我可以从左侧设置占位符填充