简体   繁体   中英

Making custom UILabel using swift in iOS having frame issues

I want to create my own custom UILabel using swift and I'm running into frame issues when using the init super class.

This is what I had before:

 let label = UILabel()

I used to basically use a normal UILabel. Firstly my question is, how is the frame set for this? Because when I step inside the UILabel class it inherits from UIView and the init method inside UIView takes a frame. So how is this frame created?

This then brings me to my own custom UILabel, which I have called TimeLabel. Here is its implementation:

class TimeLabel: UILabel {

    var clientName: String?
    var time: Time?

    init(name:String, time:Time) {
        self.clientName = name
        self.time = time
        super.init(frame: ??)
    }

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

This now links to the first question, where should I be getting this frame from? I wasn't providing a frame before when calling UILabel? How should I deal with this?

This is how you setup your class:

Remember to use "convenience" keyword. By using convenience keyword you don't need to add NSCoding protocol inherited by UIVIew.

class TimeLabel: UILabel {
    var clientName: String?
    var time: Time?

    // Use convenience keyword
    convenience init(name: String?, time: Time?) {
        self.init(frame: CGRect.zero)
        self.clientName = name
        self.time = time
    }
}

This is how you get the width and height based on the content

1. Get width and height from one-line-label

let timeLabel = TimeLabel(name: "John", time: sometime)
let size = timeLabel.sizeThatFits(CGSize.zero)

// This is the label calculated width and height
let width = size.width
let height = size.height

2. Get width and height from multi-line-label

let timeLabel = TimeLabel(name: "John", time: sometime)

// To active multiline features, set numberOfLines to 0
timeLabel.numberOfLines = 0

let size = timeLabel.sizeThatFits(CGSize(width: putYourWidthHere, height: 0))

// This is the label calculated width and height
let width = size.width
let height = size.height

1) This is how i would initialize a label with frame

UILabel(frame: CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100.0 , height: 60.0)))

2) in custom class though you can do this...

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

both are separate things.. did i get you right? ask a question if any doubt

One reference

If you don't want to provide a frame at initialization time, use CGRect.zero :

class TimeLabel: UILabel {
    var clientName: String?
    var time: Time?

    init(name:String, time:Time) {
        self.clientName = name
        self.time = time
        super.init(frame: CGRect.zero)
    }
}

You can always change the frame later, or use auto-layout and the frame will be set for you.

Your init(coder:) method should only decode your subclass' properties (if you want), and should leave everything else to the superclass:

    required init?(coder aDecoder: NSCoder) {
        // decode clientName and time if you want
        super.init(coder: aDecoder)
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM