0

I have a Swift UIView class (named HypnosisView) that draws a circle on the screen. The frame of the view is set to fill the screen. I would like to programmatically set the background color of the view upon initialization (so when an instance of the view is created it automatically has the specified background color). I was able to make this work with a convenience initializer, however I'm wondering if there is a more efficient way to do this (or if in fact I'm doing this correctly). In an ideal scenario, I would like to just add a piece of code that sets the background: self.background = UIColor.clearColor() to the inherited init(frame: CGRect) method, so I don't have to write a whole new initializer just to set the background color.
Here is my convenience initializer method (what I'm currently using which works):

convenience init(rect: CGRect){
        self.init(frame: rect)
        self.backgroundColor = UIColor.clearColor()
}

and I call that method in the delegate like this:

var mainFrame = self.window!.bounds
var mainView = HypnosisView(rect: mainFrame)

Let me know if you have any questions. Thanks!

dcgoss
  • 2,147
  • 3
  • 20
  • 31
  • Why are you using a convenience initializer? You already subclass UIView. In its **designated** initializer, set the background color. But it's basically exactly what you're doing (minus the convenience), and I don't see how you can make it any shorter. Your "whole new initializer" is simply a call to super and your own modifications. – Rikkles Aug 09 '14 at 20:10
  • @Rikkles I had tried overriding the designated initializer like this: `override init(frame: CGRect){ self.backgroundColor = UIColor.clearColor() super.init(frame: frame)}` and it threw the error: `Class "HypnosisView" does not implement its superclass's required members`, which is why I tried the convenience initializer. I'm still learning all this – dcgoss Aug 09 '14 at 20:29
  • Actually I take that back. If you use the convenience initializer it's the simplest. Because if you override `init(frame)`, you **also** must override `init(coder)` which creates more code for you. So in your case I think you've got the simplest solution. A convenience initializer that sets a property to a default value. – Rikkles Aug 09 '14 at 20:44

1 Answers1

0

As discussed in the comments, when wanting to customize the behavior of a UIView, it's often easier to use a convenience initializer as opposed to overriding a designated initializer.

For UIViews specifically, if you override the designated init(frame aRect: CGRect), you are unfortunately also required to override init(coder decoder: NSCoder!) which is part of the NSCoding protocol. So generally if you just want to set a few properties to some default values, do as the original poster asked and create a convenience initializer that in turn calls init(frame aRect: CGRect):

convenience init(rect: CGRect, bgColor: UIColor){
    self.init(frame: rect)
    self.backgroundColor = bgColor
}

For a discussion on getting rid of NSCoding compliance, see Class does not implement its superclass's required members

Community
  • 1
  • 1
Rikkles
  • 3,372
  • 1
  • 18
  • 24
  • One question: what does it mean when you have two parameter names when you say `init(frame aRect: CGRect) `? – dcgoss Aug 09 '14 at 21:06
  • Means that externally the parameter is called `frame`, but internally to the function it's called `aRect`. See "External Parameter Names" in the Swift book. – Rikkles Aug 09 '14 at 21:14