Why does forced uwrapped type with nil not crash when passed to a function argument that has optional type? [duplicate] - swift

This question already has an answer here:
Swift 3 incorrect string interpolation with implicitly unwrapped Optionals
(1 answer)
Closed 6 years ago.
I don't understand why the type system lets me do this?
In other words I would expect this to crash when foo is passed to the function.
var foo:String!
func someFunction(_ bar:String?) {
print("-- \(bar) --")
}
someFunction(foo)
=> writes "-- nil --"

As #Hamish so correctly points out here:
https://stackoverflow.com/a/39537558/308189
If the expression can be explicitly type checked with a strong optional type, it will be. However, the type checker will fall back to forcing the optional if necessary.
And the comment on the answer explains why this question was asked:
As if it weren't bad enough that you have to use an IUO, now they're less useful and behave contradictorily. If I use one it's because I want it to be implicitly unwrapped. They should be called Schrödinger Optionals from now on. – Andreas

Inside your someFunction you are printing the optional not String. that's why it is not crashing. if you want to print bar as String you have to unwrap the value.

// This line will create variable named foo and type of it will be String! and value of it will be nil.
// It mean i can access this variable is force-wraped so it may dangerous but uses of this variable without type checking compiler will not give any warning(ignore by compiler).
var foo:String!
// This function will accept `String` value or `nil`.
func someFunction(_ bar:String?) {
print("-- \(bar) --")
}
// So calling this function use of `foo`(valued nil) will not give any compiler issue.
someFunction(foo)

Related

what is the difference between "?" and "!" operator in swift?

I was just wondering what is the difference between "?" and "!" in swift, I'm new to swift. I tried looking for questions similar in here, but couldn't find any.
An optional type can be nil
var nameOfToy: String?
The toy may have a name;
nameOfToy = "Buzz"
so
print (nameOfToy!)
is Buzz.
The question mark indicates that it is optional, i.e. can be nil, so you have to UNWRAP it with the !. This is because the variable is optional.
But what happens if there is no name of a toy, and you use !. In this case you get a nasty crash.
These characters have different meanings depending on the context. More than likely you are referring to their uses in unwrapping optionals.
If you have a variable foo:
var foo: Int?
You have declared the variable as an Optional. An Optional is a variable that can contain some value, or no value (nil.) Think of an Optional as a box, or wrapper, around another data type. In order to get at the value inside the optional, you have to unwrap it.
The question mark is the unwrap operator.
Say you have a more complex object like a struct:
struct Foo {
bar: Int
}
var aFoo: Foo?
You've created an Optional instance of Foo called aFoo. The variable aFoo either contains a Foo object, or it contains nil.
You could use code like this:
if aFoo?.bar == 3 {
print("aFoo contains an int == 3")
} else {
print("aFoo is either nil or contains some other value")
}
The ! operator is the "force unwrap" operator. I call it the "crash if nil" operator. If you rewrite the code above using force-unwap:
if aFoo!.bar == 3 {
print("aFoo contains an int == 3")
}
Then there is no point in having an else clause, since if aFoo is nil, you are guaranteed to crash.
You should only use the force-unwrap operator if you are certain that the Optional is not nil.
Optionals are a very important concept in Swift, so you should study them, and the various ways to handle them, until it's second nature.
Make sure you learn about "optional chaining", "optional binding", the nil coalescing operator, guard statements, and force unwrapping, to name a few techniques to deal with optionals.
“To declare an optional, we just have to add a question mark after the type’s name.To read the value of an optional, we have to unwrap it by adding an exclamation mark at the end of the name.”
“Declaring implicitly unwrapped optionals”
“Swift provides the possibility to declare implicitly unwrapped optionals. These are optional variables declared with the exclamation mark instead of the question mark. The system reads these variables as optionals until they are assigned a value and therefore we don’t have to unwrap them anymore.”
var mynumber: Int!
mynumber = 5
var total = mynumber * 10  // 50

Swift string vs. string! vs. string?

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 a String that's guaranteed to be present. There is no way this value can be nil, thus it's safe to use directly.
String? represents a Optional<String>, which can be nil. You can't use it directly, you must first unwrap it (using a guard, if let, or the force unwrap operator !) to produce a String. As long as you don't force unwrap it with !, this too is safe.
String! also represents an Optional<String>, which can be nil. However, this optional can be used where non-optionals are expected, which causes implicit forced unwrapping. It's like having a String? and having it always be implicitly force unwrapped with !. These are dangerous, as an occurrence of nil will crash your program (unless you check for nil manually).
For your PancakeHouse struct, name is non-optional. That means that its name property cannot be nil. The compiler will enforce a requirement that name be initialized to a non-nil value anytime an instance of PancakeHouse is initialized. It does this by requiring name to be set in any and all initializers defined for PancakeHouse.
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 #IBOutlets 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."
Thanks to Andrew Madsen's answer and all other answers, I learnt a bit myself:
struct pairOfOptionalAndNonOptionalAndImplicitUnwrapped{
var word1 :String?
var word2 :String
var word3: String!
init (a:String, b: String, c: String){
self.word1 = a // Line A
self.word2 = b // Line B
self.word3 = c // Line C
} //Line BBBB
func equal() ->Bool{
return word1 == word2 + word3
}
}
let wordParts = pairOfOptionalAndNonOptionalAndImplicitUnwrapped (a:"partTwo", b: "part", c:"Two")
wordParts.equal() // Line CCCC
If I comment out Line A only, I will get no errors, because it is optional, and optionals can be set to nil.
If I comment out Line B only, I will get a compilation error on Line BBBB, saying: Return from initializer without initializing all stored properties, I get this because I have declared property word2 as non-optional. I have told the compiler I have guaranteed to have you set...
If I comment out Line C only, I will not get an error, unless I actually run a method on my object. The error you could get is: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP, subcode=0x0) if and only if I run wordParts.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)

Are type-inferred variables "optionals" by default in Swift?

In going through Apple's Swift tutorial we are introduced to optionals fairly quickly, informing us that we mark a value as optional by using a '?' character.
The example given is:
let optionalInt: Int? = 9
It goes on to say:
"To get the underlying type (my emphasis, not theirs) from an optional, you unwrap it. You’ll learn unwrapping optionals later, but the most straightforward way to do it involves the force unwrap operator (!). Only use the unwrap operator if you’re sure the underlying value isn’t nil.
let actualInt: Int = optionalInt!
This is probably excessively nitpicky, but shouldn't it say "To get the underlying value..." instead of type?
Anyways, my actual question is about the usage of the question mark. Immediately after the above example we are told:
"Optionals are pervasive in Swift, and are very useful for many
situations where a value may or may not be present. They’re
especially useful for attempted type conversions."
var myString = "7" "7"
var possibleInt = Int(myString) 7
print(possibleInt) "Optional(7)\n"
In this code, the value of possibleInt is 7, because myString
contains the value of an integer. But if you change myString to be
something that can’t be converted to an integer, possibleInt becomes nil.
myString = "banana" "banana"
possibleInt = Int(myString) nil
print(possibleInt) "nil\n"
Why, directly after telling us that optionals are declared with '?', do they give an example that is apparently using an optional without the '?'.
I tried looking at the documentation and searching other stack overflow answers and maybe I'm just missing something but for some reason I couldn't find an answer to this apparently simple question.
It's perhaps not the clearest example, because type inference is hiding the question mark. If they explicitly declared the type of possibleInt, you'd see:
var myString: String = "7" "7"
var possibleInt: Int? = Int(myString) 7
print(possibleInt) "Optional(7)\n"
What's happening is the init(_: String) initializer on Int is what's called a "failable initializer", and it returns an optional Int, aka Int?.

Why does SWIFT print "Optional(...) [duplicate]

This question already has answers here:
println dictionary has "Optional"
(2 answers)
Closed 7 years ago.
If the following code runs
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print(airports["YYZ"])
Why does the console print
Optional("Toronto Pearson")
Why does it print Optional( withValue ) and not just the value?
Why would I need to know that in the console?
Swift has optional types for operations that may fail. An array index like airports["XYZ"] is an example of this. It will fail if the index is not found. This is in lieu of a nil type or exception.
The simplest way to unwrap an optional type is to use an exclamation point, like so: airports["XYZ"]!. This will cause a panic if the value is nil.
Here's some further reading.
You can chain methods on option types in Swift, which will early exit to a nil without calling a method if the lefthand value is nil. It works when you insert a question mark between the value and method like this: airports["XYZ"]?.Method(). Because the value is nil, Method() is never called. This allows you to delay the decision about whether to deal with an optional type, and can clean up your code a bit.
To safely use an optional type without panicking, just provide an alternate path using an if statement.
if let x:String? = airports["XYZ"] {
println(x!)
} else {
println("airport not found")
}

What does an exclamation mark in a property in Swift language? [duplicate]

This question already has answers here:
What does an exclamation mark mean in the Swift language?
(23 answers)
Swift variable decorations with "?" (question mark) and "!" (exclamation mark)
(1 answer)
Closed 8 years ago.
There are three way to declare a property in Swift:
var optStr: String?
var normStr: String = "normStr"
var exactStr: String!
The first one is property with an optional type, a type that can contain either nil or the String in our case. The second one is a property that always contain the String. It should be initialized in init or in the declaration.
But what about the third way?
var exactStr: String!
I made some experiments in the playground, and it turned out that a function that takes type? can take both type, type? and type! variables as an argument:
var optStr: String?
var normStr: String
var forcedStr: String!
func printStr(str: String?) {
println("str: \(str)")
}
printStr(optStr) //prints: "str: nil"
//printStr(normStr) //doesn't compile as not initialized
printStr(forcedStr) //prints: "str: nil"
optStr = "optStr"; normStr = "normStr"; forcedStr = "forcedStr"
printStr(optStr) //prints "str: optStr"
printStr(normStr) //prints "str: normStr"
printStr(forcedStr) //prints "str: forcedStr"
So why and when should I use type!?
Update: this is not a duplicate of What does an exclamation mark mean in the Swift language?. I'm not asking about unwrapping a variable: I'm asking about declaring a property with an exclamation point (Type!).
It's a variable of type "implicitly-unwrapped optional String". Essentially, every access of implicitStr is treated as if it were written implicitStr! (thus unwrapping the value).
This, of course, will cause a crash if the value is nil. You can still test the implicit optional via if implicitStr != nil, or use it in optional chaining as var foo = implicitStr?.uppercaseString. So you can still use it just as safely as a normal optional; it's just biased toward the case where the value is not nil.
Implicitly-unwrapped optionals are quite useful in cases where the value may not be present at initialization, but are set early and unlikely to become nil again. (For example, a variable you set in -awakeFromNib might reasonably be an implicitly-unwrapped optional.)
Further, since Objective-C methods can return both nil and object types, their return values cannot be modeled as non-optional. To avoid requiring liberal use of forced unwrapping whenever dealing with Cocoa APIs, though, the parameters and return types of Cocoa APIs are usually represented as implicitly-unwrapped optionals.