0

Is it possible to set a design-time text for UILabel (or image if using UIImageView) on iOS 8? if so, how to?

Basically what I need is not to empty all of my labels before compiling so that it doesn't show dummy data before loading from the network the actual data. An algorithm to programatically clear all outlets isn't really a good solution as it is unnecessary code.

Christopher Francisco
  • 15,672
  • 28
  • 94
  • 206

1 Answers1

2

You could try subclassing the classes you want to have design-time attributes. Here is an example of that for UILabel:

import UIKit

class UIPrototypeLabel: UILabel {
    @IBInspectable var isPrototype: Bool = false

    override func awakeFromNib() {
    if (isPrototype) {
        self.text = "test"
    }
}

Then, in IB, you will see isPrototype, and you can set it to true or false.

You can also change the default from false to true in the isPrototype:Bool = false line if you want. You can also change what happens if isPrototype is true. I had it make the text "test" so I could see feedback when testing this out, so you could change it to nil or "" or whatever.

You can also just eschew the isPrototype bool and have this class always reset the text. I just thought the IBInspectable attribute was cool, but if you just want this class to always clear the label text then you would just delete the bool and the check and just self.text=nil every time.

The con to this approach is you need to make all of your labels UIPrototypeLabel to get this functionality.

enter image description here

There is a second, scarier approach, that will add this functionality to all of your UILabels, and that is extending UILabel.

import ObjectiveC
import UIKit
// Declare a global var to produce a unique address as the assoc object handle
var AssociatedObjectHandle: UInt8 = 0

extension UILabel {
    @IBInspectable var isPrototype:Bool {
        get {
            var optionalObject:AnyObject? = objc_getAssociatedObject(self, &AssociatedObjectHandle)

            if let object:AnyObject = optionalObject {
                return object as! Bool
            } else {
                return false // default value when uninitialized
            }
        }
        set {
            objc_setAssociatedObject(self, &AssociatedObjectHandle, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
        }
    }

    public override func awakeFromNib() {
        if (isPrototype) {
            self.text = "test"
        }
    }
}

credit to Is there a way to set associated objects in Swift? for some of that code

Community
  • 1
  • 1
Will M.
  • 1,864
  • 17
  • 28
  • I love your first approach, but I think we can improve it, wanna help me out :D? So basically, we would set prototype ON when designing and OFF before compiling. It'd be better if we found a way not to change between ON/OFF before compilation, and it keeps the in-design behavior. I found this link: http://nshipster.com/ibinspectable-ibdesignable/ I tried using @IBDesignable and it works with TARGET_INTERFACE_BUILDER macro; but it "auto-compiles" when you change it's value on IB – Christopher Francisco May 23 '15 at 15:22
  • You would set prototype ON if you want the label to have prototype text. If Prototype = ON, the text is overwritten at runtime, as soon as the label is awoken from NIB. For example, if the line self.text = "test" was changed to self.text = "", you would have a label where, no matter what the text was set to at design time, at runtime it would initially be set to "", and then you could set it manually. You would have to reset it manually every time it was re-awoken though – Will M. May 24 '15 at 15:58