Guard statement in swift for error handling [duplicate] - ios

This question already has answers here:
How to check if a text field is empty or not in swift
(16 answers)
Closed 6 years ago.
I tried running below statement, but it's skipped right over in the code.
guard let num1 = num1Input.text else
{
show("No input in first box")
return
}
Can somebody tell me why this statement isn't running when the text field is blank?

You could use the where clause to check for non-nil and non-empty
guard let num1 = num1Input.text where !num1.isEmpty else {
show("No input in first box")
return
}

You should check the length of the text, not if its nil i.e:
guard num1Input.text.characters.count > 0 else {
...
}
If the text is optional, you can do.
guard let num1 = num1Input.text where num1.characters.count > 0 else {
...
}

This statement is testing whether the text is nil but you probably want to test whether the string is empty, therefore
guard let input = num1Input.text where input.characters.count > 0 else {
print("empty")
return
}
or just simply
guard num1Input.text?.characters.count > 0 else {
print("empty")
return
}

Related

Provide a catch if index is out of range (Swift 5) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
When I fetch data through a GET method in Swift it is presented as an Array:
URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data else { return }
do {
let obj: Response = try JSONDecoder().decode(Response.self, from: data)
let cit = obj.assetProfile?.city
let coun = obj.assetProfile?.country
let negociosLocacion = ("\(cit ?? "N/A"), \(coun ?? "N/A")")
let object = EObject(marketOpen: (obj.price?.regularMarketOpen?.fmt ?? "N/A"))
self.e.append(object)
But how do I create a catch method where if the index is out of range will present a segue, for example, as to not crash the app?
You can use indices to check if an array contains an index prior to accessing it:
guard myArray.indices.contains(1) else { return }
let value = myArray[1]
Apple documentation: indices
You can handle it through various ways for example I am showing you some code snippets below. See what case is similar to yours.
If you are getting items by index from an array then you can avoid array index out of range error like:
if yourIndex <= yourArray.endIndex {
//Then do your desired operation by getting items by your index
} else {
//Do not get items by your index because it is out of range.
//Do anything else
}
You can check that your array is empty or not? like:
if yourArray.isEmpty {
// Don't do any array item get operations because your array is empty
} else {
// Your array is not empty
}
You can check that at least your array has a fixed number of elements or not? like:
if yourArray.count >= yourDesiredNumberOfElements {
// Your array have at least your desired number of elements.
} else {
// Your array does not have your desired number of elements.
// your array has less elements than you desire.
}
A good solution is to use a safe subscript with returns optional element.
extension Array {
public subscript(safeIndex index: Int) -> Element? {
guard index >= startIndex, index < endIndex else {
return nil
}
return self[index]
}
}
In order to check if the index is out of bounds so as to not cause the app to crash and to handle the situation in another way,
if (yourArray.count - 1) >= yourIndex {
//Not out of bounds, carry on.
} else {
//This is when your app would crash due to being out of bounds.
}

getting crash on null data with callback function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Here is my code:
func getProduct(productId: String, callback: #escaping (String) -> () ){
Transport.sharedInstance.getProduct(productId: productId) { (data, err) in
if let _ = err{
}else{
if let dt = data as? String{
let pro = Mapper<SubCategoryProducts>().map(JSONString: dt)
let com = ComboData()
com.price = pro?.Price ?? 0
com.type = pro?.type ?? ""
com.amount = pro?.quantity ?? ""
if (pro?.combodata == nil) {
pro?.combodata?.append(com)
} else if ((pro?.combodata?.contains(where: {$0.type == pro?.type})))! {
} else {
pro?.combodata?.append(com)
}
self.arrayForCombo.removeAll()
pro?.combodata?.forEach({ (com) in
let str = "\(com.amount) " + "\(com.type)" + " - " + "₹ \(com.price)"
self.arrayForCombo.append(str)
})
callback(self.arrayForCombo[0])
}
}
}
}
I am getting nil pro?.combodata so only I have checked wether I am getting nil value or not and then when it comes to callback it getting crash on here callback(self.arrayForCombo[0]). Because its not appending the values. I don't know why, but not able to achieve that. Any solution it would be helpful.
Check if forEach is even stepped into.
At this point it can be that either pro or pro.combodata are nil and forEach is not called on nil collection.
Probably you're trying to access [0] index element after self.arrayForCombo.removeAll().
Try using this:
guard let pro = Mapper<SubCategoryProducts>().map(JSONString: dt) else { return }
let com = ComboData()
com.price = pro.Price ?? 0
com.type = pro.type ?? ""
com.amount = pro.quantity ?? ""
if (pro.combodata == nil) {
pro.combodata = [com]
}
The problem is that when combodata of pro is nil than you are trying to append the object that means you are trying nil.append() while it should be [ComboData].append().
I hope this will help you.
When the optional array is nil then calling append will do nothing, you need to initialize it first
if (pro?.combodata == nil) {
pro?.combodata = []
pro?.combodata?.append(com)
}
After executing self.arrayForCombo.removeAll() statement, arrayForCombo become empty. If your pro?.combodata is nil then forEach statement could not execute. So still your arrayForCombo is empty.
But in the callBack statement you forcefully try to access the first item of arrayForCombo whether it's empty or not. That's why it crushes when the array is empty.
You can safely by pass the cruhes like that:
if let firstItem = arrayForCombo.first {
callback(firstItem)
}

Missing argument for parameter #1 in call to Swift function

Very new to Swift and coding in general.
Just need some help getting my random selector to work. I am trying to make it choose a random number between 1 and 9 and check if that number is the same as the button you click.
enter image description here
I'm guessing you're trying to compare the random number to the title (displayed number) on the clicked button?
If so, add this line above your if statement:
guard let buttonInt = sender.titleLabel?.text.flatMap(Int.init) else { return }
Then, change your if statement to look like so:
if randomNumber == buttonInt {
// do what you want if it matches
} else {
// handle no match
}
// EDIT: Props to Alexander for the flatMap version
Please check :
let rand = Int(arc4random_uniform(9))
guard let buttonInt = Int(sender.currentTitle!) else { return }
if rand == buttonInt {
} else {
}

I don't know how to make them add or subtract, its there a way to do so. Basically I want 1"+"3 = 4 but I get 1+3 [duplicate]

This question already has answers here:
Swift - Resolving a math operation in a string
(4 answers)
Closed 6 years ago.
let randsign = Int(arc4random_uniform(2) + 1)
//This function returns a random operator
func whatSign(par1:Int)-> String {
if (par1 == 1){
return "+"
}
else {
return "-"
}
}
var sigh = whatSign(par1: randsign)
let randnum1:Any = Int (arc4random_uniform(10) + 1)
let randnum2:Int = Int (arc4random_uniform(10) + 1)
//I want the variable "finVal" to perform mathematical operation, but it does not because the variable "sign" is String
let finVal = "\(randnum1)\(sigh)\(randnum2)"
print(finVal)
//When I print I get for example 1-3, 9-4, 8+2 .But I wanted them to do arithmetic
NSExpression is one the good way to evaluate the Math
let finVal = "(randnum1)(sigh)(randnum2)"
let result = NSExpression(format: finVal).expressionValue(with: nil, context: nil) as! Int
let randsign = Int(arc4random_uniform(2) + 1)
let randnum1:Any = Int (arc4random_uniform(10) + 1)
let randnum2:Int = Int (arc4random_uniform(10) + 1)
var finVal:Int
//This function returns a random operator
func whatSign(par1:Int)-> String {
//I want to compute the variables and get final result from adding or subtracting them
if (par1 == 1){
finVal = randnum1 + randnum2
return "+"
}
else {
finVal = randnum1 - randnum2
return "-"
}
}
whatSign(par1: randsign)
print(finVal)
//When I print I get for example 1-3, 9-4, 8+2 .But I wanted them to do arithmetic
Maybe it will helps you

Using If-Let and checking the output in a single line

This is just an example to illustrate what I am trying to achieve.
I want to check if an optional contains a value and if it is greater than 0. I currently have it this way:
if let value = Double(textFieldText) {
if value > 0 {
return true
}
}
Is there any way to achieve this in a single line? Something like:
if let value = Double(textFieldText) && value > 0{
return true
}
You can use where clause:
if let value = Double(textFieldText) where value > 0 {
Another option using nil coalescing operator:
if Double(textFieldText) ?? -Double.infinity > 0 {
Thanks to comments below which help me realize nil > 0 doesn't throw an error:
if Double(textFieldText) > 0 {
is by far the simplest option.
Solution in 1 line
I think the simplest way to write your logic is this
return Double(textFieldText) > 0
Test
func foo(textFieldText:String) -> Bool {
return Double(textFieldText) > 0
}
foo("1") // true
foo("-1") // false
foo("a") // false
foo("0") // false
foo("123a") // false
Why does this work?
When 2 values are compared in Swift and (exactly) one of them is nil, then nil is always less than the other value.
So every time the initialiser of Double does fail, like here
return Double("a") > 0
the expression becomes
return nil > 0
which is false.
The only way the expression does return true is when the input string is parsed as a Double value which is actually greater then 0.
Which is exactly the logic you where looking for :)
With a where clause:
if let value = Double(textFieldText) where value > 0 {
return true
}
Or simply:
if Double(textFieldText) > 0 {
return true
}
One more way you can do the same thing and that would steer you away from ugly if let nesting.
func hello(values:String) -> Bool {
guard let value = Double(values) where value > 0 else {
return false
}
return true
}
Try this.
if let value = textFieldText as? Double where value > 0 {
return true
}

Resources