IBOutlets and IBactions require ! in the end
Asked Answered
A

7

7

I tried to start and go from Obj-C to Swift today and I was reading the documentation. I tried to create an easy IBOutlet in Swift and it constantly gave me those errors.

View Controller has no initialiser

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

IBOutletproperty has non-optional type 'UILabel'

and that constantly pops up with this code:

@IBOutlet var outputLabel : UILabel

but when I add an ! mark, it's running without errors like so

@IBOutlet var outputLabel : UILabel!

Same thing happens for IBActions...

Anatolic answered 18/12, 2014 at 8:20 Comment(4)
I would suggest tot read the second answer: #24007475 It is quite useful.Pettifer
@DánielNagy may i ask, I checked some video tutorials online and they never put the !... Why don't they and we have to? ThanksAnatolic
The video tutorials could be out of date - originally the IBOutlet decorator made the property optional as well, this was changed very early on.Borax
yeah, as @Borax said. Right now you have to put the ! at the and, because it will have its value only after the initialization.Pettifer
G
11

First of all get to know, what is actually ! and ?

  • Use ? : if the value can become nil in the future, so that you test for this.
  • Use ! : if it really shouldn't become nil in the future, but it needs to be nil initially.

@IBOutlet:

When you declare an outlet in Swift, the compiler automatically converts the type to a weak implicitly unwrapped optional and assigns it an initial value of nil.

In effect, the compiler replaces @IBOutlet var name: Type with @IBOutlet weak var name: Type! = nil.

Xcode would change it and Force restrict on declare @IBOutlet non option type variable , so following both kind of declaration for @IBOutlet is Valid till date.

@IBOutlet var outputLabel : UILabel!
@IBOutlet var priceLabel : UILabel?

However, if you control drag an outlet for a label in beta 4 this happens:

@IBOutlet var priceLabel : UILabel! = nil
Govan answered 18/12, 2014 at 8:54 Comment(1)
Thanks!! So I will just put it. And that covers the tutorial aspect then... OkayAnatolic
L
7

Interface builder data is loaded after view controller has been initiated, so outlets cannot have value after initialisation. With implicitly unwrapped optional properties (outlets in this case) you promise that properties might be nil after object is initiated, but their value will be assigned later (after the load of nib or storyboard).

Lucent answered 18/12, 2014 at 8:30 Comment(0)
C
6

That is correct. In Swift, a variable of type X cannot be nil, meaning it has to be initialized. This means that you must initialize either in a init method, or inline initialize.

Generally, view controllers will declare variables of types that are optional - for example,

@IBOutlet var outputLabel : UILabel!

This means that you do not need to initialize the outputLabel, and by default, it's value is nil. This is the general pattern for IBOutlet variables, as the variables are set outside of the init method.

If you do not make your variables optional, you must initialize it. If you do not initialize inline, you must provide an init method - hence the error that you are getting.

Cloudlet answered 18/12, 2014 at 8:29 Comment(3)
How do I provide a init in swift?Anatolic
You need to look at the view controller and override one of the init methods. For example, you have one here: required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }Cloudlet
To provide an initialiser is to miss the point, though. Outlets aren't populated on init, they are populated when the view is loaded, and will be nil until that point.Borax
A
1

As Stack allows Q and A style questions, I'll also put it into easier words. Just put the ! at the and of outlets guys. Thanks a lot for your help.

Anatolic answered 18/12, 2014 at 8:51 Comment(0)
H
0

The error

'required' initialized 'init(coder:)' must be provided by subclass of 'UIViewController' 

suddenly started when I added

var start : NSDate

to a previously working subclass of UIViewController otherwise all made in IB. Changing to

 var start : NSDate?

fixed. It is such a surprising error (huh? init? coder?) for a simple edit someone starting an app could make long before they encounter coders or create their own init methods, that perhaps it helps to show explicitly that initialization need is not confined to IBOutlets. The answers above describe the root cause.

Hindward answered 20/2, 2015 at 18:44 Comment(0)
D
0

When views or view controllers are initialized from an interface builder file, their outlets cannot be connected yet. They will only be connected after initialization, so they need to be optional. When any other code in the class is called after initialization, though, these outlets are guaranteed to be connected. This is why IBOutlets are always declared as implicitly unwrapped optionals.

Dyan answered 15/11, 2017 at 10:26 Comment(0)
S
0

While it seems like XCode is blessing this behavior, it's still unsafe and you always keep in mind that you might want to make some Optionals.

While IB will initialize these for you, that doesn't guarantee they won't become nil later ... for example, if you need to remove an IBOutlet as a subview, or conditionally set a NSLayoutConstraint.isActive = false (which an annoyingly stealthy nil).

Swot answered 7/10, 2019 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.