IBOutlets and IBactions require ! in the end

大兔子大兔子 提交于 2019-12-03 08:15:06
virus

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

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

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.

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.

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.

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.

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!