Swift Subclass Uiview

Swift subclass UIView

I usually do something like this, its a bit verbose.

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()

(Edit: I've edited my answer so that the relation between the initializers is more clear)

What is the steps to create a subclass for UIView that adds border?]

There's a pretty detailed answer here:

Proper practice for subclassing UIView?

Basically, you should override:

init?(coder aDecoder: NSCoder) and init(frame: CGRect) as well as awakeFromNib(). Just call another function from there where you set the border.

How to properly init passed property in subclass of UIView?

If you want to initialize a UIView with a custom property you must reconfigure its initializer:

class InputWithIncrementView: UIView {
let inputName: String

init(inputName: String) {
self.inputName = inputName
super.init(frame: .zero)
}

required init?(coder aDecoder: NSCoder) {
return nil
}
}

Subclassing a UIView

Think about what you expect to happen in…

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

and

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

You have a non-optional instance variable title. How is it supposed to get a value in these 2 cases?

And in your 3rd init

convenience init(title: String) {
self.title = title
self.init(title: title)
}

init(title: String) calls init(title: String), which in turn calls init(title: String), etc. You're in infinite recursion territory.

If you want to instantiate the view in code, you'll need something like…

init(title: String, frame: CGRect) {
self.title = title
super.init(frame: frame)
alertLayout()
}

and you'll also need to implement

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

If you're using this in a storyboard / nib, then you'll need…

required init?(coder aDecoder: NSCoder) {
self.title = ""
super.init(coder: aDecoder)
}

and then assign a value to title afterwards

accessing UIView subclass in view controller

Posting my own answer.

  1. Create the XIB file.
  2. Create the UIView subclass Swift file.
  3. Under the XIB file owner's Identify Inspector custom class field, type in the UIView subclass name (your custom view).
  4. Under the XIB file owner's Connections Inspector, make sure all IBOutlets in the Swift file are connected.
  5. Add a view to the view controller and under its Identify Inspector custom class type, specify the custom class name.

Important:
* In your XIB swift file, you have to properly load the XIB content view.

...

/// Initializer used by Interface Builder.
required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}

/// Initializer used programmatically.
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}

...

func configure() {
let contentView = // here use many of the functions available on the internet to
// load a view from a nib.
// Then add this view to the view hierarchy.
addSubview(contentView)
}

How do I write a custom init for a UIView subclass in Swift?

The init(frame:) version is the default initializer. You must call it only after initializing your instance variables. If this view is being reconstituted from a Nib then your custom initializer will not be called, and instead the init?(coder:) version will be called. Since Swift now requires an implementation of the required init?(coder:), I have updated the example below and changed the let variable declarations to var and optional. In this case, you would initialize them in awakeFromNib() or at some later time.

class TestView : UIView {
var s: String?
var i: Int?
init(s: String, i: Int) {
self.s = s
self.i = i
super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
}

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

Swift UIView subclass with auto layout

Why are you giving the label heightAnchor?

If you want it to be automatically resized depends on the text all you to do is:

  1. numberOfLines is 0 for the label
  2. give top,leading,bottom and trailing anchors for the label to its super view
  3. super view should at least has top,leading and trailing anchors to its super view (View controller view) where you are going to add this custom view.

DONT forget while init the custom view set the property translatesAutoresizingMaskIntoConstraints to false

Use @IBInspectable with any UIView subclass within storyboards

Move your code to UIView's @IBDesignable extension like below:

@IBDesignable extension UIView {    
@IBInspectable var cornerRadius: CGFloat {
set {
layer.cornerRadius = newValue
layer.masksToBounds = true
}
get {
return self.cornerRadius
}
}
}

Clear unwanted values/types of previously deifned vars in your GEView. Here are values in inspector.

Sample Image

Properties available in inspector of any UIView, included itself.

Properties avaliable in storyboard interface

How to get a UIView subclass instance from its ViewController in Swift

Screenshot 1 - Test project
Screenshot 2 - Property inspector

I've just put this quick example together, Notice in the screenshot that the IBOutlet has a type of CustomView.

What I done was to add the UIView in the storyboard and then change the class in the property inspector to CustomView and THEN created the IBOutlet. This then used the correct type, so I could reference the custom properties and functions of the view.

You can update the type in your outlet if you created it before as long as it matches up with the class in the property inspector.



Related Topics



Leave a reply



Submit