I have read this question and some other questions. But they are somewhat unrelated to my question
For UILabel
if you don't specify ?
or !
you will get such an error:
@IBOutlet property has non-optional type 'UILabel'
Which then Xcode gives you 2 choices to have it fixed, you can do:
fix-it Add ? to form the optional type UIlabel?
fix-it Add ! to form the implicitly unwrapped optional type UIlabel?
However for string you can just type string
without ?
or !
and you won't get an error why is that?
What happens if the name
isn't set? Then we would have a nil
isn't using ?
, !
and Swift all about satisfying 'type-safety'?
Example:
struct PancakeHouse {
let name: String // this doesn't have '?' nor '!'
let photo: UIImage?
let location: CLLocationCoordinate2D?
let details: String
}
My major confussion is when would we want to not use Optional?
All this is covered in the documentation: The Swift Programming Language - The Basics.
In short:
String
represents aString
that's guaranteed to be present. There is no way this value can be nil, thus it's safe to use directly.String?
represents aOptional<String>
, which can benil
. You can't use it directly, you must first unwrap it (using aguard
,if let
, or the force unwrap operator!
) to produce aString
. As long as you don't force unwrap it with!
, this too is safe.String!
also represents anOptional<String>
, which can benil
. However, this optional can be used where non-optionals are expected, which causes implicit forced unwrapping. It's like having aString?
and having it always be implicitly force unwrapped with!
. These are dangerous, as an occurrence ofnil
will crash your program (unless you check fornil
manually).Thanks to Andrew Madsen's answer and all other answers, I learnt a bit myself:
Return from initializer without initializing all stored properties
, I get this because I have declared propertyword2
as non-optional. I have told the compiler I have guaranteed to have you set...Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0)
if and only if I runwordParts.equal()
, because I told my code that it's an optional meaning that it will be set from elsewhere after instantiation/compilation. Meaning that lldb can through me a runtime error if you it didn't get set. ( the error would happen on line CCCC)For your
PancakeHouse
struct,name
is non-optional. That means that itsname
property cannot be nil. The compiler will enforce a requirement thatname
be initialized to a non-nil value anytime an instance ofPancakeHouse
is initialized. It does this by requiringname
to be set in any and all initializers defined forPancakeHouse
.For
@IBOutlet
properties, this is not possible. When an Interface Builder file (XIB or Storyboard) is unarchived/loaded, the outlets defined in the IB file are set, but this always occurs after the objects therein have been initialized (e.g. during view loading). So there is necessarily a time after initialization but before the outlets have been set, and during this time, the outlets will be nil. (There's also the issue that the outlets may not be set in the IB file, and the compiler doesn't/can't check that.) This explains why@IBOutlet
properties must be optional.The choice between an implicitly unwrapped optional (
!
) and a regular optional (?
) for@IBOutlet
s is up to you. The arguments are essentially that using!
lets you treat the property as if it were non-optional and therefore never nil. If they are nil for some reason, that would generally be considered a programmer error (e.g. outlet is not connected, or you accessed it before view loading finished, etc.), and in those cases, failing by crashing during development will help you catch the bug faster. On the other hand, declaring them as regular optionals, requires any code that uses them to explicitly handle the case where they may not be set for some reason. Apple chose implicitly unwrapped as the default, but there are Swift programmers who for their own reasons, use regular optionals for@IBOutlet
properties.The whole "optional" thing messed with me bad at first. What made it "click" for me, was when I stopped thinking of those as "String" objects and started thinking of them as generics. Just like "Array" with generic identifier for "String" is an array that, if it has values, contains strings... "String?" is an Optional that, if it has a value, is a string.
String - This is always guaranteed to be some kind of string, and NEVER nil. When you declare a variable, it must be given a value.
String? - This is an optional. It can be nil, and IF it has a value, it will be a string. In order to access the optional's value, you must unwrap it.
String! - This is an optional, with syntax sugar that lets you access its value directly as if it where just a String. It COULD be nil, but for whatever reason, the context around the variable has winked at you and said "don't worry, it will have a value."