As the title I've just asked, I want to know which case we should use ? = nil
For example :
var text: String? // text will be initialized with nil
var text: String? = nil // text will be assigned to nil
So what is the diffrence between them. When we should use ? = nil
As it says in the Swift Language documentation:
You use optionals in situations where a value may be absent. An optional says: There is a value, and it equals x or there isn’t a value at all
There is no difference between ? and ? = nil. The ? = syntax allows you to assign a default (a word they should perhaps use in the documentation for the sake of clarity) value of your choosing.
So if there is no value at all: ? or, if there is a value, and it equals x, then: ? = <some value>
Related
var result = (dimensione-base)/2
dimensione & base are two "Double?" number, how can i solve this?
i want to calculate this, but he always gives me this error:"Binary operator - cannot be applied to two "double?" operands.
Double? is an optional type. That means a variable of this type can be nil. So before making an operation with them, you need to make sure these variables actually hold a value :
if let dimensione = dimensione,
let base = base
{
var result = (dimensione-base)/2
// Use result here
}else{
// Do something here when dimensione or base is nil.
}
You could also prefer to assign them a default value when they are nil (but in this case it seems less secure) :
var result = ((dimensione ?? 0)-(base ?? 0))/2
Here, if nil, 0 will be used instead.
I have a function where string value is defined based on value in dictionary. If value in dictionary is not found, I set it to static string. String is constant (let):
let dict = [ 1: "a",
2: "b" ]
func x() {
let index = someFunctionReturnsInt()
let str = (nil != dict[index]) ? dict[index] : "N/A"
So string cannot possibly be nil. However, when I try to use str, Swift still considers it an optional. For example:
// still inside the same function
os_log("Str is %#", str)
will return a compiler error:
Value of optional type 'String?' must be unwrapped to a value of type 'String'
Thing is, I use this function quite a few times, and adding str ?? "N/A" on every occasion makes no sense. Force-unwrap with str! seems like an overkill: this string is not critical to the app, so I don't think aborting execution if it's missing makes any sense.
So is force-unwrap the only solution, or is there a better way to define a string as non-optional and "never going to be nil"?
The issue is that dict[index] is still returning an optional so str has to be an optional. There are two ways you can fix it
You can use the nil coalescing operator to use dict[index] if its not nil otherwise use "N/A"
let str = dict[index] ?? "N/A"
Another option is to use the dictionary default value subscript
let str = dict[index, default: "N/A"]
You should simply use the nil coalescing operator when defining the str itself. Checking if the value is nil, then still assigning the optional value without unwrapping makes no sense.
let str = dict[index] ?? "N/A"
You should use nil coalescing operator - let str = dict[index] ?? "N/A"
Instead of let str = (nil != dict[index]) ? dict[index] : "N/A"
The reason because str is still optional in your case is because dict[index] is optional even if you are checking it to be no nil. So, swift infers the type of str to be String?
You could also force unwrap because you are already checking it to be no nil like -
let str = (nil != dict[index]) ? dict[index]! : "N/A"
But force unwrapping should be avoided whenever possible
I'm new to Swift and I'm wondering if there's a 'short hand' form of assigning Optional values to non-optional values without doing if nil check.
For example if I've got an Optional closure:
var onTap: (() -> Void)?
I can later on call this via
onTap?()
The ? let's me skip the nil check and force unwrap.
But I'm curious if something exists for values that are not clousre. For example
var oldTransform: CGAffineTransform?
var someTransform: CGAffineTransform //non optional
and later on, I decide to assign oldTransform to someTransform I have to
if (oldTransform != nil) {
someTransform = oldTransform!
}
Is there a pattern that's less verbose to do the above (kinda of like the ?)?
Yes, of course. You could use if let as below:
if let unwrappedOldTransForm = oldTransform {
someTransform = unwrappedOldTransForm
}
When you check with if let, it will unwrap the value for you and check if it can set the value of oldTransform to unwrappedOldTransForm. If the value is nil you will be able to handle the error by adding an else condition as below:
if let unwrappedOldTransForm = oldTransform {
someTransform = unwrappedOldTransForm
} else {
// handle if oldTransform is nil
}
In the case of a function, as you know, "calling" a nil function (like onTap?()) has no effect - but for an assignment to a non-optional type you need to supply a definite non-optional value. For that you can use the nil-coalescing operator ?? like so:
var optionalString: String?
// ... maybe set optionalString ...
var realString: String = optionalString ?? "<some default value>"
In your example, it would be
someTransform = oldTransform ?? CGAffineTransform(...) // some default - say Identity
or even, as commentator #user28434 suggests
someTransform = oldTransform ?? someTransform // assuming someTransform already initialised
which will only change someTranform if oldTransform isn't nil.
In each case, the left hand operand of ?? will be assigned if is non-nil, otherwise the right hand side operand will be assigned.
What is the difference between:
var title:String? = "Title" //1
var title:String! = "Title" //2
var title:String = "Title" //3
What am I saying if I were to set title in each way and am I forced to unwrap each variable in a different way?
Think about ? and ! like a box that might have a value or not.
I recommend this article.
Optional box that might have value or might not, and that optional box is not unwrapped.
var title:String? = "Title" //second and third picture
You use unwrapped value like that:
if let title = title {
//do sth with title, here is the same like let title: String = "Title"
}
Optional box that might have a value or might not, and that optional box is actually unwrapped. If there is a value and you access that value, that is ok (second image, just replace ? with !), but if there is no value, then app crash (third image, just replace ? with !)
var title:String! = "Title"
That variable have a value for sure, and you cannot assign to this value nil (because it is not optional). Optional means that there is a value or there is no value (nil):
var title:String = "Title" //first picture
`var title:String? = "Title"`
title currently has a value of Title, but in the future it could possibly be nil. I will need to unwrap it using optional binding:
if let unwrappedTitle = title {
println(unwrappedTitle)
}
Or by forcing the unwrap with the ! character
let unwrappedTitle = title!
The above will crash if title is nil
`var title:String! = "Title"`
title currently has a value of "Title". It could possibly be nil, but I know that it never will be when I am using it. You don't need to unwrap this with optional binding or by forcing the unwrap with the ! character.
Your program will crash if this value is ever accessed while nil, but the compiler will let you set this value to nil.
`var title:String = "Title"`
title currently has a value of "Title". This may change, but the variable title will always have some string value. I don't need to check for nil with optional binding or by forcing an unwrap. The compiler will not let you build if you try to set title to nil.
var title:String? = "Title" //1 Nil Possible-Force Unwrap needed-Nil checking when use
var title1:String! = "Title"//2 Nil Possible-Force Unwrap not needed-Nil cheking when Use
var title2:String = "Title" //3 Nil Not possible as its initailize when declared-No force unwrap needed-No Nil Cheking is needed.
I want to use an Optional variable with the ternary conditional operator but it is throwing error this error: optional cannot be used as boolean. What am I doing wrong?
var str1: String?
var myBool:Bool
myBool = str1 ? true : false
You can not assign string value to bool but You can check it str1 is nil or not like this way :
myBool = str1 != nil ? true : false
print(myBool)
It will print false because str1 is empty.
Nil Coalescing Operator can be used as well.
The code below uses the ternary conditional operator and forced unwrapping (a!) to access the value wrapped inside a when a is not nil, and to return b otherwise
Normal Ternary Operator :
output = a != nil ? a! : b
Apple Developer Link : Please refer to Demo Link
In Swift 1.2 & 2, above line of code is replaced by a shorter format:
output = a ?? b
Demo Link : The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil.
This even works well if the value you want is a property or result of a function call on an optional (in Swift 3.0):
return peripheral?.connected ?? false
Ternary operators operate on three targets. Like C, Swift has only one
ternary operator, the ternary conditional operator (a ? b : c).
Example usage on tableView -
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 2 ? 4 : 1
}
indicates if section equal to 2 then it return 4 otherwise 1 on false.
To add on the already very good answers, sometimes you need the convenience of the ternary operator but also need to perform changes on the wrapped value, such as;
var fullName = lastName != nil ? "\(firsName) \(lasName!)" : firstName
But you don't want to force unwrap (even though this situation would be fine).
Then you can actually use Optional.map:
var fullName = lastName.map({ "\(firstName) \($0)" }) ?? firstName
The completion block passed to .map is only called if the wrapped value ($0) is not nil. Otherwise, that function just returns nil, which you can then easily coalesce with the ?? operator.
In case the comparison is based on some condition
let sliderValue = Float(self.preferenceData.getLocationRadius().characters.count > 1 ?self.preferenceData.getLocationRadius():"0.1")
Here the function getLocationRadius() returns a String. One more thing if we don't put a space between 1 and ? it results in an syntax error