IBOutlets and IBactions require ! in the end

2020-06-03 08:58发布

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...

7条回答
成全新的幸福
2楼-- · 2020-06-03 09:40

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

查看更多
趁早两清
3楼-- · 2020-06-03 09:50

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.

查看更多
爷、活的狠高调
4楼-- · 2020-06-03 09:51

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.

查看更多
成全新的幸福
5楼-- · 2020-06-03 09:55

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

查看更多
Lonely孤独者°
6楼-- · 2020-06-03 09:57

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.

查看更多
戒情不戒烟
7楼-- · 2020-06-03 09:59

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
查看更多
登录 后发表回答