How is a return value of AnyObject! different from AnyObject - swift

The NSMetadataItem class in the Cocoa framework under Swift contains the following function:
func valueForAttribute(key: String!) -> AnyObject!
I'm still learning the difference (and details) between forced unwrapping and optional chaining. In the above function, does this mean:
The key parameter must have a value, and
The return value is guaranteed to have a value?
My primary concern is with the exclamation point following the return value - once I have assigned the return value:
var isDownloadedVal = item.valueForAttribute(NSMetadataUbiquitousItemIsDownloadedKey)
Do I need to include an if let block when examining it, or am I guaranteed that it will have a value I can examine safely?

TLDR: Treat Foo! as if it were Foo.
Many Cocoa calls include implicitly unwrapped optionals, and their need for it is very likely the reason the feature even exists. Here's how I recommend thinking about it.
First, let's think about a simpler case that doesn't involve AnyObject. I think UIDevice makes a good example.
class func currentDevice() -> UIDevice!
What's going on here? Well, there is always a currentDevice. If this returned nil that would indicate some kind of deep error in the system. So if we were building this interface in Swift, this would likely just return UIDevice and be done with it. But we need to bridge to Objective-C, which returns UIDevice*. Now that should never be nil, but it syntactically could be nil. Now in ObjC, we typically ignore that fact and don't nil-check here (particularly because nil-messaging is typically safe).
So how would we express this situation in Swift? Well, technically it's an Optional<UIDevice>, and you'd wind up with:
class func currentDevice() -> UIDevice?
And you'd need to explicitly unwrap that every time you used it (ideally with an if let block). That would very quickly drive you insane, and for nothing. currentDevice() always returns a value. The Optional is an artifact of bridging to ObjC.
So they invented a hack to work around that (and I think it really is a hack; I can't imagine building this feature if ObjC weren't in the mix). That hack says, yes, it's an Optional, but you can pretend it's not, and we promise it's always going to be a value.
And that's !. For this kind of stuff, you basically ignore the ! and pretend that it's handing you back a UIDevice and roll along. If they lied to you and return nil, well, that's going to crash. They shouldn't have lied to you.
This suggests a rule: don't use ! unless you really need to (and you pretty much only need to when bridging to ObjC).
In your specific example, this works in both directions:
func valueForAttribute(key: String!) -> AnyObject!
Technically it takes an Optional<String>, but only because it's bridged to NSString*. You must pass non-nil here. And it technically returns you Optional<AnyObject>, but only because it's bridged to id. It promises that it won't be nil.

According to the Swift-eBook, which states the following
„Trying to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value.“
I would answer to your first two questions with Yes.
Do I need to include an if let block when examining it...
No, this is not necessary.

Related

Difference between two optional syntaxes in Swift

What is difference between
self?.profile!.id!
and
(self?.profile!.id!)!
XCode converts first to second.
The first one contains self? which means self is optional, leads to let related properties (profile!.id! in your case) related to the existence of the self which is Optional Chaining:
Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil. If
the optional contains a value, the property, method, or subscript call
succeeds; if the optional is nil, the property, method, or subscript
call returns nil. Multiple queries can be chained together, and the
entire chain fails gracefully if any link in the chain is nil.
To make it more simpler, you could think of id! nullity is also optional, even if you force unwrapping it, because it is related to the existence of self; If self is nil, profile and id will be also nil implicitly because they are related to the existence of self.
Mentioning: (self?.profile!.id!)! means that the whole value of the chain would be force wrapped.
Note that implementing:
self!.profile!.id!
leads to the same output of
(self?.profile!.id!)!
since self! is force unwrapped, the value of id would not be related to the nullity of self because the compiler assumes that self will always has a value.
However, this approach is unsafe, you should go with optional binding.
First of all you are using too many question and exclamation marks!!!
Practically there is no difference. The result is a forced-unwrapped optional.
Usually Xcode suggests that syntax if the result of the last item of the chaining is a non-optional so the exclamation mark would cause an error for example
text?.count!
Then Xcode suggests
(text?.count)!
but in this case be brave and write
text!.count

Why to avoid forced unwrapping

There are cases where you forgot to set a value (so it's actually a bug), and running the program with forced unwrapping can crash the problem, and that can allow you to track down the bug where you forgot to set the value that you should have set.
From posts talking about avoiding forced unwrapping, it's always brought up that forced unwrapping can crash the program therefore it's a bad thing. What's so bad about crashing a problem when it actually has a bug?
Please give examples where forced unwrapping can be bad.
(I'm not saying forced unwrapping is suitable for everything.)
Forced unwrapping (and I'm going to include force-casting as well) should only be used when you, as the programmer, know for a fact that an optional will never actually ever be nil unless that nil represents a clear bug in your code during development (and then you want it to crash).
There are many examples where this type of forced unwrapping is appropriate. Examples include:
Getting the path to a known file in your app bundle (nil means you forgot to target the file during development).
Force casting a call to UITableView dequeueReusableCell (nil means you have a mistake in your storyboard).
Getting a specific component from DateComponents when you just specially asked Calendar for that component (nil mean you have a typo).
There are obviously many other cases where forced-unwrapping is appropriate but you must have a clear understanding of those cases.
But there are just as many runtime decisions that result in optionals that you can't guarantee and such cases should not be forced unwrapped.
Examples include:
Dealing with any user input. Never assume a user enters valid data. Never assume a value can be converted as expected. Always check for nil results.
Parsing JSON results. Never assume the data you get matches some expected format even if that format is clearly documented and always seems to work. Things change over time. Gracefully handle such unexpected data instead of just assuming a value will always be there and of the assumed data type.
Dealing with any API that can throw or return optional results. Things can go wrong. Errors happen. Never assume you will get back a valid answer. Code defensively.
In the end, a developer with the proper experience and understanding of how optionals work, what they mean, and when a value may or may not ever actually be nil is in a position to safely use forced unwrapping when appropriate. Use it wisely.
Never use forced-unwrapping just because Xcode suggested it to make the compiler happy.
Forced unwrapping is bad because your program is not guaranteed to be accessing an actual variable at the time of execution. When this happens your program might be attempting to perform a mathematical calculation on a number that doesn't exist, and your app would crash. Your point of in the development phase if it crashes you would be able to narrow down why the crash happened and fix the issue of it being nil at runtime for your development phase, but what about in production?
For example, if you were retrieving some sort of number from a web service you may want to compare this number to something local, maybe a version number:
if let json = try? JSONSerialization.jsonObject(with: responseData, options: .allowFragments) as? [String: Any],
let serverAPIVersion:NSNumber = json["API_Version_Number"] as? NSNumber {
if self.currentAPIVersion.uintValue < serverAPIVersion.uintValue {
self.updateVersionWith(number: serverAPIVersion)
}
}
In the code above we are safely unwrapping the "API_Version_Number" from the JSON we get from the server. We are safely unwrapping because if there weren't a value for "API_Version_Number" then when we would try to do the comparison to the current version, the program would crash.
// This will crash if the server does not include "API_Version_Number in json response data
let serverAPIVersion:NSNumber = json["API_Version_Number"] as! NSNumber
And in production there are things out of your control (many times a server side issue) that may lead to unpopulated variables. That is why it is best to conditionally unwrap to gain access to values safely in your code to keep things from crashing at execution time.
There's nothing wrong with crashing a program if it actually has a bug...if you can not work your way around the crash
But as #phillip-mills says in his comment:
...asked by people who use forced unwrapping without understanding that's what's causing the crash
We often see examples where people force unwrap optionals that, for some unexpected reason, isn't there, and in that case it makes sense to try to unwrap the optional "gracefully.
An Example of Bad Forced Unwrapping
Lets say you have a backend service that gives you some JSON which you parse into a model object and present in a view.
Lets say you have a model like this one:
struct Person {
let firstName: String?
let lastName: String?
}
And in a UITableView you populate some cells with person objects. Something along the lines of:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//dequeue your cell
//get your person element from some array
//populate
cell.firstNameLabel.text = person.firstName!
cell.lastNameLabel.text = person.lastName!
return cell
}
At some point you probably will end up with a Person without a firstName (you can say that that is a problem with the backend and so on and so forth but....it'll probably happen :) ) If you force unwrap, your app will crash where it shouldn't be necessary. In this case you could have gotten away with a graceful unwrap
if let firstName = person.firstName {
cell.firstNameLabel.text = firstName
}
Or you could have used the Nil Coalescing Operator
let firstName = person.firstName ?? ""
Finally, as #rmaddy says in his answer
Forced unwrapping is bad because your program is not guaranteed to be accessing an actual variable at the time of execution
You can not always be sure that the data is what you expect it to be.
And when you have the possibility to actually only do some operation if you're absolutely sure that the data you're operating on is valid, that is, if you've unwrapped it safely...it'd be stupid not to use that option :)
Hope that helps you.

optional value error found nil swift 3

I was trying to assign a value to a var but I get this error: fatal error: unexpectedly found nil while unwrapping an Optional value.
the code:
vehicle.chassis = Chasis.text
but the variable is not an optional, I declare the variable this way:
var vehicle: Vehicle!
how can I fix this problem?
check the image
You are trying to set a property to an instance that doesn't exist, because the implicitly unwrapped Optional vehicle is nil.
You can't set vehicle.chassis if vehicle is nil.
Before accessing .chassis you have to populate vehicle somewhere with an instance of Vehicle, for example in an init, or in viewDidLoad, etc:
vehicle = Vehicle()
and then you can access the .chassis property:
vehicle.chassis = Chasis.text
To clarify what some of the above commenters have already mentioned, you're declaring your property as an Implicitly Unwrapped Optional (IUO herein). Only optionals in Swift can be nil, but optionals must be unwrapped, IUO's don't need to be unwrapped, but might crash. IUO's exist for 2 reasons.
To provide an unsafe/more raw access to your property to achieve ingrained Objective-C design patterns more quickly. That is, directly act on "pointers" that may or may not be nil and crash when it is.
To provide a non-optional interface to properties that you cannot guarantee will be initialized by the time your class/struct init finishes, but you can guarantee will be initialized by the time you use it. Useful for something the compiler can't verify but you as a programmer can.
That being said, I can only think of 2 sane proper ways to use IUO's in a Swifty manner, 1 is for IBOutlets, these aren't compiled by the swift compiler, don't exist after init(), but are guaranteed to be fulfilled by the time you use it (if your nib isn't corrupt), perfect use case for IUO's.
Another, while less imperative since it can be designed around, is Database models where you want lazy reads (which in itself is a bit of a pain to implement anyway)

Dictionary containing an array - Why is unwrapping necessary?

I'm trying to wrap my head around why what feels intuitive is illegal when it comes to a dictionary containing an array in Swift.
Suppose I have:
var arr = [1,2,3,4,5]
var dict = ["a":1, "b":2, "test":arr]
I can easily access the dictionary members like so:
dict["a"]
dict["b"]
dict["test"]
As expected, each of these will return the stored value, including the array for key "test":
[1,2,3,4,5]
My intuitive reaction to this based on other languages is that this should be legal:
dict["test"][2]
Which I would expect to return 3. Of course, this doesn't work in Swift. After lots of tinkering I realize that this is the proper way to do this:
dict["test"]!.objectAtIndex(2)
Realizing this, I return to my intuitive approach and say, "Well then, this should work too:"
dict["test"]![2]
Which it does... What I don't really get is why the unwrap isn't implied by the array dereference. What am I missing in the way that Swift "thinks?"
All dictionary lookups in Swift return Optional variables.
Why? Because the key you are looking up might not exist. If the key doesn't exist, the dictionary returns nil. Since nil can be returned, the lookup type has to be an Optional.
Because the dictionary lookup returns an Optional value, you must unwrap it. This can be done in various ways. A safe way to deal with this is to use Optional Chaining combined with Optional Binding:
if let value = dict["test"]?[2] {
print(value)
}
In this case, if "test" is not a valid key, the entire chain dict["test"]?[2] will return nil and the Optional Binding if let will fail so the print will never happen.
If you force unwrap the dictionary access, it will crash if the key does not exist:
dict["test"]![2] // this will crash if "test" is not a valid key
The problem is that Dictionary’s key-based subscript returns an optional – because the key might not be present.
The easiest way to achieve your goal is via optional chaining. This compiles:
dict["test"]?[2]
Note, though, that the result will still be optional (i.e. if there were no key test, then you could get nil back and the second subscript will not be run). So you may still have to unwrap it later. But it differs from ! in that if the value isn’t present your program won’t crash, but rather just evaluate nil for the optional result.
See here for a long list of ways to handle optionals, or here for a bit more background on optionals.
In the Objective-C world, it has potential crash if you are trying to access 3 by dict[#"test"][2]. What if dict[#"test"] is nil or the array you get from dict[#"test"] has two elements only? Of course, you already knew the data is just like that. Then, it has no problem at all.
What if the data is fetched from the backend and it has some problems with it? This will still go through the compiler but the application crashes at runtime. Users are not programmers and they only know: The app crashes. Probably, they don't want to use it anymore. So, the bottom line is: No Crashes at all.
Swift introduces a type called Optional Type which means value might be missing so that the codes are safe at runtime. Inside the Swift, it's actually trying to implement an if-else to examine whether data is missing.
For your case, I will separate two parts:
Part 1: dict["test"]! is telling compiler to ignore if-else statement and return the value no matter what. Instead, dict["test"]? will return nil if the value if missing. The terminology is Explicit Unwrapping
Part 2: dict["test"]?[2] has potential crash. What if dict["test"]? returns a valid array and it only has two element? This way to store the data is the same using dict[#"test"][2] in Objective-C. That's why it has something called Optional Type Unwrapping. It will only go the if branch when valid data is there. The safest way:
if let element = dict["test"]?[2] {
// do your stuff
}

What's the meaning of as!,init? in swift?

Sometime when I use "as" ,xcode prompts failed and suggests change to "as!".Also I see some construstors is "init?".I know some variables could be difined as optional.What the meaning of a constructor to be optionsal?
I looked up the questions in "the swift programming language",but failed to get the answer.
Use
as
When you believe that a constant or variable of a certain class type may actually refer to an instance of a subclass.
Using
as?
will always return an optional value and if the downcasting wasn't possible it will return nil.
Using
as!
is forced unwrapping of the value. Use "as!" when you're sure that the optional has a value.
init?
is used to write fail-able initialisers. In some special cases where initialisations can fail you write fail-able initiasers for your class or structure.
For your as!-Question please look here. as! force unwraps your optional.
Regarding your init?-Question: This is called a failable initializer. Basically this means your init-method can fail and it will return nil. See the Swift Blog for reference.
If your object can only be created if some condition is met then init? makes sense, since it could return an object or nil. As for as! you should only use that if you're absolutely certain the object is of that type, otherwise use this paradigm:
if let object = obj as? String { ... } .