Swift optional types thoughts - ios

I have a question about: " I guess why it work, but i should ask it here to check my thoughts :D.
I have a code:
let possibleNumber = "1232"
var somevariable : Int
if let actualNumber = Int(possibleNumber) {
somevariable = actualNumber
} else {
print("\(possibleNumber) could not be converted to an integer")
}
print(somevariable)
and mistake: Variable 'somevariable' used before being initialized
But if i had something like this:
let possibleNumber = "1232"
var somevariable : Int
if let actualNumber = Int(possibleNumber) {
somevariable = actualNumber
} else {
somevariable = 0
}
print(somevariable)
It will work without any problems.
If i delete the else block it'l make an error too. In any case, i understand it in that meaning like: i don't allow you to make a situation when somevariable can be nil because his type is not optional.
Maybe my thoughts are wrong or you have a better explanation. Thanks for any help and good links.
Good luck!

Your thought is right this
if let actualNumber = Int(possibleNumber)
has a possibility of not being true , and as else doesn't assign a value , hence the error , also you'll get the same error if you only assigned it inside else only , the compiler needs to make sure the value isn't nil because it doesn't know which block ( if or else ) will run at runtime , so depending on your conditions you have to either use Int! or Int? , but the former will cause a crash if the value is nil

The somevariable is used without initialization. So in the first code, there is a possibility to reach the else clause so the somevariable is not initialized.
But in the second case even in the else clause, somevariable is initialized and =0.
These codes work too:
let possibleNumber = "1232"
var somevariable : Int?
if let actualNumber = Int(possibleNumber) {
somevariable = actualNumber
} else {
print("\(possibleNumber) could not be converted to an integer")
}
print(somevariable)
And this:
let possibleNumber = "1232"
var somevariable : Int!
if let actualNumber = Int(possibleNumber) {
somevariable = actualNumber
} else {
print("\(possibleNumber) could not be converted to an integer")
}
print(somevariable)

Related

In Swift, how do I do 'if let' instead of this?

I'd like to use 'if let' here but I can't get it to work. Can someone help me?
guard animal?.img != nil else {
print ("image is nil")
return
}
let animalImage = UIImage(data: animal!.img!) as UIImage?
saveImageView.image = animalImage
I think you mean "guard let". BTW, you almost always want to avoid force unwrapping.
Also since UIImageView.image is optional you don't need to check the returned value from UIImage constructor
guard let data = animal?.img else {
print ("image data is nil")
return
}
saveImageView.image = UIImage(data: data)
There are several things you can do with an optional value:
var optionalText:String?
...
var text4:String? = optionalText // assign it to another optional variable
var text5 = optionalText // the same, the compiler will infer that text5 is also an optional string
optionalText?.append(" hello") // will only call `append(_:)` on `text` if it's not nil, otherwise this will be ignored
let text6:String = optionalText ?? "It was nil!" // use the coalescing operator
let text7:String = optionalText! // force-unwrap it into a String; if it's nil, your app will crash
// you CANNOT, however, treat it as a non-optional:
let newText = "Hello " + optionalText // this won't compile
// you can unwrap it:
if let text8 = optionalText {
// this code block will ONLY execute if textField.text was not nil
let newString = "Hello "+ text8 // this constant will only work in this block
// in that case, text8 will be of type String (non-optional)
// so it shouldn't be treated as an optional
}
let newString = "Hello "+ text8 // this won't compile
// unwrap it with `guard`:
guard let text8 = optionalText else {
// this code block will ONLY execute if textField.text WAS nil
// and it must return
return
}
let newString = "Hello "+ text8 // this is okay, text8 lives on in case of `guard`
These are the differences between guard let and if let:
if let nonOptional = optional {} will assign a value to a non-optional constant by unwrapping an optional value and execute the code block, but only if the optional isn't nil. The non-optional constant will only live inside the if let { } block. Use this if you want to handle both cases (nil or otherwise) and then move on with your code.
guard let nonOptional = optional else { } will do the same assignment if possible, but code flow will be different afterwards: it will execute the else block in case the optional value is nil, and that else block will have to quit the scope (return, continue, or break); it must not fall through, i.e. execution must not continue right after the block (the compiler will make sure of that). However, your nonOptional constant will live on after this statement. Use this if your code largely depends on the optional value not being a nil: quit early if the condition fails, and otherwise hold on to the non-optional value and use if for the rest of your enclosing scope.
Btw., you can also use var instead of let if it makes sense, in both cases.
The main purpose of guard is to avoid the "pyramid of doom" type of nested checks:
// pyramid of doom
func doomed() {
if condition1 {
if condition2 {
if condition3 {
// success scenario
print("all good")
// ...
} else {
print("failed condition 3")
return
}
} else {
print("failed condition 2")
return
}
} else {
print("failed condition 1")
return
}
}
// avoiding pyramid of doom
func nonDoomed() {
guard condition1 else {
print("failed condition 1")
return
}
guard condition2 else {
print("failed condition 2")
return
}
guard condition3 else {
print("failed condition 3")
return
}
// success scenario
print("all good")
// ...
}
Without guard, your success scenario is hidden in the middle of nested if statements related to error conditions, making your code difficult to read or edit.
With guard, each error condition is handled separately, and after you get them out of the way, you can go on with the success scenario. With guard let, you can also ensure that all the necessary constants and variables are available for the rest of the scope.
What you seem to need is one of two things:
Optionally unwrap and use your optional:
if let realImage = animal?.img {
let animalImage = UIImage(data: animal!.img!) as UIImage?
saveImageView.image = animalImage
}
// otherwise, saveImageView.image will not be assigned a new value
Simply pass an optional value
saveImageView.image = animal?.img
This should work because the left-hand side and the right-hand side are both UIImage? optionals.
This should do it, you assign your image data to first variable, then use it to assign to the second one:
if let img = animal?.img, let animalImage = UIImage(data: img) {
//do something
}
Probably don't need as? Data and as? UIImage, it depends on your model.
You can do it like below...
if let imgName = animal?.img {
saveImageView.image = UIImage(data: imgName)
}
I would extend Data and create an image property to return an optional image from your data object:
extension Data {
var image: UIImage? { UIImage(data: self) }
}
Usage:
saveImageView.image = animal?.img?.image
This would allow you to provide a default image as well in case of nil using the nil coalescing operator:
saveImageView.image = animal?.img?.image ?? UIImage(named: "defaultImage")
guard let and if let are effectively the same thing. In fact, if you are guarding the first statement to check if it's nil anyway, you can combine them into a single check and do something like this:
guard let animalImageData = animal?.img,
let animalImage = UIImage(data: animalImageData) else { return }
saveImageView.image = animalImage
or alternatively,
if let animalImageData = animal?.img, let animalImage = UIImage(data: animalImageData) {
saveImageView.image = animalImage
}
When you force-unwrap animal!.img!, it is unsafe practice and should generally be avoided since it could lead to fatal exceptions.

How to prevent iOS app from crashing due to empty textfields?

I need to figure out a solution to prevent the app from crashing when a value is not entered in a textfield. The idea is if the textfield is empty (nil), the value of that textfield will then equal zero. Below I have copied my code:
let taxPercentDou:Double = Double(taxnosign2!)!
Anyone has any suggestions?
You need to stop force unwrapping optionals with the exclamation ! sign:
let b:Double = Double(rent.text!)!// Rent
If rent.text is nil or contains non-numeric text, your app will crash.
You can check for nil and replace it with "0" using the null coalescing operator:
rent.text ?? "0"
You can pass that into the Double initializer like this:
Double(rent.text ?? "0")
However, this will return nil if rent.text contains non-numeric text. You can use the null coalescing operator again to handle this:
let b: Double = Double(rent.text ?? "0") ?? 0.0
You could take this one step farther and write a simple utility method to make it easier to use for all your fields:
func convertToDouble(text: String?) -> Double {
return Double(text ?? "0") ?? 0.0
}
And call it like this:
let b = convertToDouble(rent.text)
Please find the below code. It Might Help you.
static func isNull(aString: AnyObject?) -> Bool
{
//Check for null
if(aString is NSNull){
return true
}
if(aString == nil){
return true
}
let x: AnyObject? = aString
//if string is nsnumber , convert it into string and check
if(aString is NSNumber){
var aString1 : String? = ""
aString1 = String(describing: aString)
return self.isStringEmpty(aString: aString1!)
}
if let aString1 = x as? String
{
return self.isStringEmpty(aString: aString1)
}
else
{
return true
}
}

Not able to check the condition on submit button swift

Short description :
I am getting one value called UserValue. This will come from one response.And i have one Confirm button press method. In that each time i need to check whether the user entered amount is greater then UserValue amount.
but some time the value will be UserValue will be nill.That time it should not check whethere entered amount in text filed is greater than UserValue
Now here my code :
#IBAction func confirmButnClicked(_ sender: Any) {
print(UserValue)
let Mvalue = Double((UserValue.formattedAmount()))
let stringValue = Int(Mvalue!)
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}
Its working fine when i got some value in UserValue but when i get nill value here its crashing...How can i handle this:
let stringValue = Int(Mvalue!) // crash here
Thanks in advance !!
You are forcefully unwrapping the nil, Due to that its crashing.
Check the UserValue is nil or not. If not nil then do the comparison
#IBAction func confirmButnClicked(_ sender: Any) {
print(UserValue)
if let UserValue = UserValue {
if let Mvalue = Double((UserValue.formattedAmount())) {
if let stringValue = Int(Mvalue) {
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}
}
}
}
Instead of force casting MValue to Int you will get error when MValue is nil or anyother type content except integer
let stringValue = Int(Mvalue!)
use like below
if let stringValue = Int(Mvalue) {
//Now it prints your perfect unwrapping value
if doubleValue < stringValue {
DialogUtils.showMessageWithOk(controller: self, message: "Maximum Value is : \(UserValue)")
}
}

Swift: Nil is incompatible with return type String

I have this code in Swift:
guard let user = username else{
return nil
}
But I'm getting the following errors:
Nil is incompatible with return type String
Any of you knows why or how I return nil in this case?
I'll really appreciate your help
Does your function declare an optional return type?
func foo() -> String? { ...
See more on: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html
NOTE
The concept of optionals doesn’t exist in C or Objective-C. The
nearest thing in Objective-C is the ability to return nil from a
method that would otherwise return an object, with nil meaning “the
absence of a valid object.”
You have to tell the compiler that you want to return nil. How do you that? By assigning ? after your object. For instance, take a look at this code:
func newFriend(friendDictionary: [String : String]) -> Friend? {
guard let name = friendDictionary["name"], let age = friendDictionary["age"] else {
return nil
}
let address = friendDictionary["address"]
return Friend(name: name, age: age, address: address)
}
Notice how I needed to tell the compiler that my object Friend, which I'm returning, is an optional Friend?. Otherwise it will throw an error.
*Does your function declare an optional return type?
func minAndmax(array:[Int])->(min:Int, max:Int)? {
if array.isEmpty {
return nil
}
var currentMin = array[0]
var currentMax = array[0]
for value in array {
if value < currentMin {
currentMin = value
}
else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minAndmax(array: [8, -6, 2, 109, 3, 71]) {
print(bounds)
}

if let variable - Use of unresolved identifier

I am using SwiftyJSON to call some APIs and fetch some data.
When I use:
if let variable = json["response"]["fieldname"] {
} else {
println("error")
}
I am not able to use the variable later on, for example to append the value to an array.
For example:
if let variable1 = json["response"]["fieldname1"] {
} else {
println("error")
}
if let variable2 = json["response"]["fieldname2"] {
} else {
println("error")
}
var currentRecord = structure(variable1, variable2) ---> This line returns an error (use of unresolved identifier variable1) as not able to find variable1 or variable2
myArray.append(currentRecord)
How can I solve this?
The scope of an if let is inside the brackets immediately following it:
if let jo = joseph {
// Here, jo is in scope
} else {
// Here, not in scope
}
// also not in scope
// So, any code I have here that relies on jo will not work
In Swift 2, a new statement, guard was added, that seems to have exactly the kind of behaviour you want:
guard let jo = joseph else { // do something here }
// jo is in scope
If you're stuck in Swift 1, though, an easy way for you to unwrap those variables without a pyramid of doom is:
if let variable1 = json["response"]["fieldname1"], variable2 = json["response"]["fieldname2"] {
var currentRecord = structure(variable1, variable2)
myArray.append(currentRecord)
} else {
println("error")
}
#oisdk already explained that the scope of a variable defined by if let is only inside the braces of that statement.
That's what you want, because if it if let statement fails, the variable is undefined. The whole point of if let is to unwrap your optional safely, so that inside the braces, you can be sure the variable is valid.
Another solution to your problem (in Swift 1.2) is to use multiple if let statements:
if let variable1 = json["response"]["fieldname1"],
let variable2 = json["response"]["fieldname2"]
{
//This code will only run if both variable1 and variable 2 are valid.
var currentRecord = structure(variable1, variable2)
myArray.append(currentRecord)}
else
{
println("error")
}
Your code checks variable2 always even variable 1 fails. But that causes (edited!) not the error.
You can check and assign both variables in the same line. The "true" branch will be executed only if both variables are not nil
let response = json["response"]
if let variable1 = response["fieldname1"], variable2 = response["fieldname2"] {
let currentRecord = structure(variable1, variable2)
myArray.append(currentRecord)
} else {
println("error")
}

Resources