2
votes

When writing a new swift class, I'm still not 100% comfortable when (not) to use implicitly unwrapped optionals as opposed to just plain optionals. As far as I can tell, it should be ok to assign something as implicitly unwrapped (and optional) if you never expect it's value to be nil. If it is nil, it's an exceptional event and should cause a runtime error.

Take, for example, this simple sign-in view that contains two textfield member variables:

class SignInFieldView : UIView {

var emailField: UITextField!;
var passField: UITextField!;

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

convenience override init(frame: CGRect) {
    self.init(frame: frame);
    commonInit();
}

func commonInit() {
    layoutEmail();
    layoutPass();
}

// MARK: Layout Text Fields

func layoutEmail() {
    let rect = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: (bounds.size.height * 0.5));
    emailField = UITextField(frame: rect);
    addSubview(emailField);
}

func layoutPass() {
    let rect = CGRect(x: bounds.origin.x, y: bounds.origin.y + (bounds.size.height * 0.5), width: bounds.size.width, height: (bounds.size.height * 0.5));
    passField = UITextField(frame: rect);
    addSubview(passField);
}
}

In the above class, both emailField and passField are classified as implicitly unwrapped optionals because I never expect them to be nil throughout the life of their superview. I don't assign them as constants because I want their initialization to be dependent on the state of the superview (frame / bounds / etc). I left out that extra code to keep this example clean.

Is using implicitly unwrapped optionals for members of initialization a proper and valid use?

1
I'm new to Swift, but my understanding is that implicitly unwrapped optionals are mostly about making it easier to work with existing APIs designed for Objective-C (where it is not unusual for methods to return nil or an object). I think you can use non-optionals in this code and refactor your commonInit into class methods so that you can initialise emailField and passField from your initialisers.Clafou

1 Answers

5
votes

I'd stay away from implicitly unwrapped optionals unless there is a good reason to use them. Use non optional, when possible, otherwise optionals. Implicitly unwrapped are very dangerous if improperly used because they bypass the compiler check and generate runtime exceptions.

Non exhaustive list of cases when to use implicitly unwrapped:

  • when there's an API returning an implicitly unwrapped
  • to solve the Strong Reference Cycles Between Class Instances problem
  • when you have a class/struct property that (by design) will never be nil, but it cannot be set in the initializer

A typical case of the latter usage is in a UIViewController, when a property is initialized in the viewDidLoad method rather than in an initializer - it makes sense to use an implicitly unwrapped.

Do not use implicitly unwrapped in this cases:

  • because it's cool
  • because it lets you save a key press on the keyboard
  • when you are not 100% sure whether to use it or not

In your specific case, although the properties are instantiated in the initializator, they depend from the superclass initialization, so it makes sense to declare them as implicitly unwrapped.