Why is a non-optional value printed as optional? - swift

I've read Non-optional shown as optional on print but that doesn't help my question.
I'm returning a Integer, but once it's printing it's being printed as optional. Why?
I'm trying to solve a code challenge. The goal is to:
Write an extension for collections of integers that returns the number
of times a specific digit appears in any of its numbers.
Here is my implementation:
extension Collection where Iterator.Element == Int {
func challenge37(count character : Character) -> Int?{
guard nil != Int(String(character)) else{
print("character wasn't an integer")
return nil
}
var counts : [Int] = []
for item in self{
var counter = 0
let stringInt = String(describing: item)
for currentCharacter in stringInt.characters{
if character == currentCharacter{
counter += 1
}
}
counts.append(counter)
}
guard let min = counts.min() else{
print("no min")
return nil
}
return min
}
}
As you can see here I'm printing it:
print([5,15,512,522].challenge37(count: "5")) // Optional(1)

Inside the function your returning an Int. However the actual signature of your method is Int? meaning it is in fact an optional and you got it wrong!
Basically your method signature is correct. But when you call the function you're getting an optional as the response and must unwrap it.
print([5,15,512,522].challenge37(count: "5")!) // 1
Additionally had you paid close attention you would have noticed that Xcode must gave you a warning (and solutions to solve it)
Expression implicitly coerced from Int? to Any
Xcode gave you the warning because it found out that you're attempting to print an optional and knows that's usually unwanted. Obviously its solution is to unwrap it either through force unwrap or defaulting.

Related

I can't understand the swift language question mark operator in dictionary in this situation transitions[prev]?[transition] [duplicate]

This question already has answers here:
What is an optional value in Swift?
(15 answers)
When two optionals are assigned to an if let statement, which one gets unwrapped? Swift language
(1 answer)
Closed 5 years ago.
I've searched in a lot of places and communities among the internet to find what the heck is happening in this programing syntax.
I'm seeking, desperately, for guidance in this code.
What is happening with the compiler in these specific declarations?
transitions[prev]?[transition]
transitions[state]?[transition] != nil
This is how the class is declared
public final class StateMachine<State: Hashable, Transition: Hashable>
This is the variables
public var state: State
private var transitions = [State:[Transition:State]]()
And these are the examples:
First situation - What is happening in the transitions[prev]?[transition]
public final func advance(transition: Transition, observe: Observer? = nil) -> State {
let prev = state
if let next = transitions[prev]?[transition], next != prev {
state = next
observe?(prev, next)
}
return state
Second situation - What is happening in the return transitions[state]?[transition] != nil
public final func canAdvance(transition: Transition) -> Bool {
return transitions[state]?[transition] != nil
}
That's all i want to understand. What is happening in these moments?
The question mark operator signifies optionality in Swift.
You can declare many things a optional, meaning they could be nil or hold a value. This includes for example variable declarations, computed properties, return values of functions and callbacks/closures. Also certain operations like casting or retrieving values from dictionaries will yield optional values.
When you want to use the value contained you have to unwrap them, cause there might not be one and the may be pointing to nil. There are many ways and forms of unwrapping and optionality chaining.
Explaing your particular examples:
In a dictionary retrieving a stored value via a key as in myDict[myKey] returns an optional value. The value for the key stored within your specific dictionary is another dictionary. By declaring transitions[state]?[transition] you say basically "if there is a dictionary found for the key state, go ahead and continue with this dictionary and get the value for the key transition for that dictionary, otherwise use nil".
This code:
return transitions[state]?[transition] != nil
is basically a shorter way of writing this:
if let stateDict = transitions[state] {
return stateDict[transition] != nil
} else {
return false
}
Your other example is about an optional closure passed into a function. You can also pass optional closures into functions and call them via closure?(). The ? signifies that if nil is passed for the closure, nothing should be done, otherwise it should be executed.
This code:
observe?(prev, next)
is basically a shorter way of writing this:
if let observeClosure = observe {
observeClosure(prev, next)
}
Some more optionality explanations:
If you work with an optional value from a declared variable you can safely unwrap it like so:
func square(myValue: Int?) → Int {
guard let myValue = myValue else {
return 0
}
return myValue * myValue
}
or
func square(myValue: Int?) → Int {
if let myValue = myValue {
return myValue * myValue
} else {
return 0
}
}
or you could define a fallback with the ?? operator
func square(myValue: Int?) → Int {
return myValue ?? 0 * myValue ?? 0
}
You could also use the ! operator to unwrap unsafely and if nil is found your app would crash. You should never do that unless you can guarantee that nil cannot be found like in:
func square(myValue: Int?) → Int {
if myValue != nil {
myValue! * mayValue! {
} else {
return 0
}
}
In brief, transitions[state]?[transition] from time to time can be nil.
So, if let next = transitions[prev]?[transition] unwraps this variable moves the algorithm inside if-parenthesis
if let next = transitions[prev]?[transition] {
// this code executes here if 'transitions[prev]?[transition]' is not nil
state = next
observe?(prev, next) // this closure possibly can be nil. if nil Swift just skips this line
}

Unwrap variable which is not optional?

I came across these lines of code for a simple calculator app.
func processOperation (operation: Operation) {
if currentOperation != Operation.Empty {
if runningNumber != "" {
rightValStr = runningNumber
runningNumber = ""
if currentOperation == Operation.Multiply {
result = "\(Double(leftValStr)! * Double(rightValStr)!)"
} else if currentOperation == Operation.Divide {
result = "\(Double(leftValStr)! / Double(rightValStr)!)"
} else if currentOperation == Operation.Subtract {
result = "\(Double(leftValStr)! - Double(rightValStr)!)"
} else if currentOperation == Operation.Add {
result = "\(Double(leftValStr)! + Double(rightValStr)!)"
}
leftValStr is declared as var leftValStr = ""
rightValStr is also declared as var rightValStr =""
I am wondering what the purpose of using "!" in \(Double(leftValStr)! / Double(rightValStr)!) is for?
From what I know, "!" is for unwrapping optional. leftValStr and rightValStr here are not declared as Optional so why do we have to unwrap them?
Even if leftValStr and rightValStr are not optionals, you are force unwrapping Double(leftValStr) and Double(rightValStr) and the result of initializing Double with a String value can be nil.
For example, you can't initialize a Double with a stackoverflow String.
If you'd like to make sure that this conversion result is correct you can use an if let to avoid force unwrapping, for example:
if let leftValDouble = Double(leftValStr) {
// do your code
} else {
// handle error
}
Please remember that if you force unwrap a nil value, your code will crash.
The Double initializer that you are using is a failable initializer, i.e. it might create a Double or return nil.
Example,
Double("3"), here "3" can be converted into Double, so it returns an optional Double value corresponding to 3.
Double("abc"), here "abc" cannot be converted into Double, so it returns nil in this case.
In your code, you are using Double(""), which also cannot be converted into Double, hence it returns nil.
Now, when you force unwrap a nil value, it will result in runtime exception.
Hence, Double(leftValStr)! results in runtime exception.
Trying to use ! to access a nonexistent optional value triggers a
runtime error. Always make sure that an optional contains a non-nil
value before using ! to force-unwrap its value.

Idiomatic way to unwrap an integer string input

Sorry if this is a basic question, but I am learning Swift and I don’t understand how to unwrap inputs from readLine().
For example, I would expect this
let n: Int = Int(readLine(strippingNewline: true) ?? -1)
to work, but it doesn’t. Nor does replacing the -1 with a "-1" to match types.
let n: Int = Int(readLine(strippingNewline: true) ?? "-1")
What is the “right” way to do this then? Can someone explain exactly what Swift is doing when it unwraps optionals and uses them as arguments for a constructor like Int?
The whole concept of optionals is a bit foreign to me (a Python programmer); in Python you handle invalid input the “ghetto way”, putting out fires only after they happen:
try:
n = int(input())
except ValueError:
n = None
but I assume the paradigm in Swift is different.
There are two optionals at play here.
First, readLine(strippingNewline: true) is optional. It can return nil if there's no input recieved prior to the End of File (EOF) character being received. It must be unwrapped before being passed into Int()
Secondly, Int() is optional, because the String it was given may not be a valid string representation of a number.
Do not use -1 in Swift to represent "no value". This is called a sentinel value, and it's exactly what optionals are invented to prevent. How do you distinguish between a -1 meaning "no/invalid input", and a -1 meaning "the user's input was -1?
Here is how I would write this code:
guard let userInput = readLine(strippingNewline: true) else {
// If we got to here, readLine(strippingNewLine:) returned nil
fatalError("Received EOF before any input was given")
}
// If we got to here, then userInput is not nil
if let n = Int(userInput) {
// If we got to here, then userInput contained a valid
// String representation of an Int
print("The user entered the Int \(n)")
}
else {
// If we got to here, then userInput did not contain a
// valid String representation of an Int.
print("That is not a valid Int.")
}

Converting from Int to String Swift 2.2

Dears
I have this case where chatId is a property of type Int
let StringMessage = String(self.listingChat?.messages.last?.chatId)
When I debug I find that StringMessage is returning Optional(15) Which means it is unwrapped. But at the same time XCode does not allow me to put any bangs (!) to unwrap it. So I am stuck with Unwrapped Variable. I know its noob question but it I really cant get it. Your help is appreciated.
Thank you
It depends on what you want the default value to be.
Assuming you want the default value to be an empty string (""), You could create a function or a method to handle it.
func stringFromChatId(chatId: Int?) -> String {
if let chatId = chatId {
return String(chatId)
} else {
return ""
}
}
let stringMessage = stringFromChatId(self.listingChat?.messages.last?.chatId)
Or you could handle it with a closure.
let stringMessage = { $0 != nil ? String($0!) : "" }(self.listingChat?.messages.last?.chatId)
If you don't mind crashing if self.listingChat?.messages.last?.chatId is nil, then you should be able to directly unwrap it.
let StringMessage = String((self.listingChat?.messages.last?.chatId)!)
or with a closure
let stringMessage = { String($0!) }(self.listingChat?.messages.last?.chatId)
Update
Assuming chatId is an Int and not an Optional<Int> (AKA Int?) I missed the most obvious unwrap answer. Sorry, I was tired last night.
let StringMessage = String(self.listingChat!.messages.last!.chatId)
Force unwrap all the optionals along the way.
Optionals have a very nice method called map (unrelated to map for Arrays) which returns nil if the variable is nil, otherwise it calls a function on the (non-nil) value. Combined with a guard-let, you get very concise code. (I've changed the case of stringMessage because variables should begin with a lower-case letter.)
guard let stringMessage = self.listingChat?.messages.last?.chatId.map { String($0) } else {
// Do failure
}
// Success. stringMessage is of type String, not String?
I think:
let StringMessage = String(self.listingChat?.messages.last?.chatId)!

Printing optional variable

I am trying with these lines of code
class Student {
var name: String
var age: Int?
init(name: String) {
self.name = name
}
func description() -> String {
return age != nil ? "\(name) is \(age) years old." : "\(name) hides his age."
}
}
var me = Student(name: "Daniel")
println(me.description())
me.age = 18
println(me.description())
Above code produces as follow
Daniel hides his age.
Daniel is Optional(18) years old.
My question is why there is Optional (18) there, how can I remove the optional and just printing
Daniel is 18 years old.
You have to understand what an Optional really is. Many Swift beginners think var age: Int? means that age is an Int which may or may not have a value. But it means that age is an Optional which may or may not hold an Int.
Inside your description() function you don't print the Int, but instead you print the Optional. If you want to print the Int you have to unwrap the Optional. You can use "optional binding" to unwrap an Optional:
if let a = age {
// a is an Int
}
If you are sure that the Optional holds an object, you can use "forced unwrapping":
let a = age!
Or in your example, since you already have a test for nil in the description function, you can just change it to:
func description() -> String {
return age != nil ? "\(name) is \(age!) years old." : "\(name) hides his age."
}
To remove it, there are three methods you could employ.
If you are absolutely sure of the type, you can use an exclamation mark to force unwrap it, like this:
// Here is an optional variable:
var age: Int?
// Here is how you would force unwrap it:
var unwrappedAge = age!
If you do force unwrap an optional and it is equal to nil, you may encounter this crash error:
This is not necessarily safe, so here's a method that might prevent crashing in case you are not certain of the type and value:
Methods 2 and three safeguard against this problem.
The Implicitly Unwrapped Optional
if let unwrappedAge = age {
// continue in here
}
Note that the unwrapped type is now Int, rather than Int?.
The guard statement
guard let unwrappedAge = age else {
// continue in here
}
From here, you can go ahead and use the unwrapped variable. Make sure only to force unwrap (with an !), if you are sure of the type of the variable.
Good luck with your project!
For testing/debugging purposes I often want to output optionals as strings without always having to test for nil values, so I created a custom operator.
I improved things even further after reading this answer in another question.
fileprivate protocol _Optional {
func unwrappedString() -> String
}
extension Optional: _Optional {
fileprivate func unwrappedString() -> String {
switch self {
case .some(let wrapped as _Optional): return wrapped.unwrappedString()
case .some(let wrapped): return String(describing: wrapped)
case .none: return String(describing: self)
}
}
}
postfix operator ~? { }
public postfix func ~? <X> (x: X?) -> String {
return x.unwrappedString
}
Obviously the operator (and its attributes) can be tweaked to your liking, or you could make it a function instead. Anyway, this enables you to write simple code like this:
var d: Double? = 12.34
print(d) // Optional(12.34)
print(d~?) // 12.34
d = nil
print(d~?) // nil
Integrating the other guy's protocol idea made it so this even works with nested optionals, which often occur when using optional chaining. For example:
let i: Int??? = 5
print(i) // Optional(Optional(Optional(5)))
print("i: \(i~?)") // i: 5
Update
Simply use me.age ?? "Unknown age!". It works in 3.0.2.
Old Answer
Without force unwrapping (no mach signal/crash if nil) another nice way of doing this would be:
(result["ip"] ?? "unavailable").description.
result["ip"] ?? "unavailable" should have work too, but it doesn't, not in 2.2 at least
Of course, replace "unavailable" with whatever suits you: "nil", "not found" etc
To unwrap optional use age! instead of age. Currently your are printing optional value that could be nil. Thats why it wrapped with Optional.
In swift Optional is something which can be nil in some cases. If you are 100% sure that a variable will have some value always and will not return nil the add ! with the variable to force unwrap it.
In other case if you are not much sure of value then add an if let block or guard to make sure that value exists otherwise it can result in a crash.
For if let block :
if let abc = any_variable {
// do anything you want with 'abc' variable no need to force unwrap now.
}
For guard statement :
guard is a conditional structure to return control if condition is not met.
I prefer to use guard over if let block in many situations as it allows us to return the function if a particular value does not exist.
Like when there is a function where a variable is integral to exist, we can check for it in guard statement and return of it does not exist.
i-e;
guard let abc = any_variable else { return }
We if variable exists the we can use 'abc' in the function outside guard scope.
age is optional type: Optional<Int> so if you compare it to nil it returns false every time if it has a value or if it hasn't. You need to unwrap the optional to get the value.
In your example you don't know is it contains any value so you can use this instead:
if let myAge = age {
// there is a value and it's currently undraped and is stored in a constant
}
else {
// no value
}
I did this to print the value of string (property) from another view controller.
ViewController.swift
var testString:NSString = "I am iOS Developer"
SecondViewController.swift
var obj:ViewController? = ViewController(nibName: "ViewController", bundle: nil)
print("The Value of String is \(obj!.testString)")
Result :
The Value of String is I am iOS Developer
Check out the guard statement:
for student in class {
guard let age = student.age else {
continue
}
// do something with age
}
When having a default value:
print("\(name) is \(age ?? 0) years old")
or when the name is optional:
print("\(name ?? "unknown") is \(age) years old")
I was getting the Optional("String") in my tableview cells.
The first answer is great. And helped me figure it out. Here is what I did, to help the rookies out there like me.
Since I am creating an array in my custom object, I know that it will always have items in the first position, so I can force unwrap it into another variable. Then use that variable to print, or in my case, set to the tableview cell text.
let description = workout.listOfStrings.first!
cell.textLabel?.text = description
Seems so simple now, but took me a while to figure out.
This is not the exact answer to this question, but one reason for this kind of issue.
In my case,
I was not able to remove Optional from a String with "if let" and "guard let".
So use AnyObject instead of Any to remove optional from a string in swift.
Please refer link for the answer.
https://stackoverflow.com/a/51356716/8334818
If you just want to get rid of strings like Optional(xxx) and instead get xxx or nil when you print some values somewhere (like logs), you can add the following extension to your code:
extension Optional {
var orNil: String {
if self == nil {
return "nil"
}
return "\(self!)"
}
}
Then the following code:
var x: Int?
print("x is \(x.orNil)")
x = 10
print("x is \(x.orNil)")
will give you:
x is nil
x is 10
PS. Property naming (orNil) is obviously not the best, but I can't come up with something more clear.
With the following code you can print it or print some default value. That's what XCode generally recommend I think
var someString: String?
print("Some string is \(someString ?? String("Some default"))")
If you are printing some optional which is not directly printable but has a 'to-printable' type method, such as UUID, you can do something like this:
print("value is: \(myOptionalUUID?.uuidString ?? "nil")")
eg
let uuid1 : UUID? = nil
let uuid2 : UUID? = UUID.init()
print("uuid1: \(uuid1?.uuidString ?? "nil")")
print("uuid2: \(uuid2?.uuidString ?? "nil")")
-->
uuid1: nil
uuid2: 0576137D-C6E6-4804-848E-7B4011B40C11