Checking values within tuple that contains only booleans - swift

I've constructed a tuple:
var groupUsersFlags = (false, false, false, false)
Throughout the screen these values get flipped over to true. So:
groupUsersFlags.0 = true
groupUsersFlags.1 = true
etc..
Is there any way to check if all the values are true at some point?

I would agree with the idea of using another data type in this case.
However, to answer the question, you can check if all the values are true like this:
groupUsersFlags.0 && groupUsersFlags.1 && groupUsersFlags.2 && groupUsersFlags.3
Or, using reflection (use as your own risk):
Mirror(reflecting: groupUsersFlags).children.reduce(true) { $0 && $1.value as! Bool }

let x = Mirror(reflecting: groupUsersFlags)
var isAllTrue = true
for value in x.children.enumerate() where value.element.value as? Bool != nil{
if value.element.value as! Bool == false {
isAllTrue = false
break
}
}
Try out this solution.

Related

How to check the string doesn’t contain any letters in swift?

i have trouble during making the letter checker, my code is like this: if !containLetters(“1234h”){print(“pass”)}
my function is
func containsOnlyNum(input: String) -> Bool {
var ok = false
for chr in input {
for check in "1234567890.-"{
if chr == check{
ok = true
}
}
if ok != true{
return false
}
}
return true
}
If I check for “h” then didn’t pass, but if i check for ”1h” then it still pass! Please help me to fix this problem. I will give a big thank for anyone who helped me
The simplest way to fix the algorithm is this way:
func containsOnlyNum(input: String) -> Bool {
// check every character
for chr in input {
var isNum = false
for check in "1234567890.-"{
if chr == check {
isNum = true
// if we have found a valid one, we can break the iteration
break
}
}
if !isNum {
return false
}
}
return true
}
print(containsOnlyNum(input: "1234")) // true
print(containsOnlyNum(input: "1234h")) // false
However, then you can directly simplify it to:
func containsOnlyNum(input: String) -> Bool {
return input.allSatisfy { chr in
"1234567890.-".contains(chr)
}
}
which does exatly the same but uses allSatisfy and contains functions, which represent the logical operators ALL and EXISTS.
However, programmers normally use regular expressions for similar tasks:
func containsOnlyNum(input: String) -> Bool {
return input.range(of: "^[0-9.\\-]+$", options: .regularExpression) != nil
}
You can check that a string contains only the characters you're interested in like this:
extension String {
var containsOnlyNum: Bool {
let wanted = CharacterSet.decimalDigits
.union(CharacterSet(charactersIn: "-."))
return unicodeScalars
.allSatisfy(wanted.contains)
}
}
"-12.34".containsOnlyNum // true
"A1234".containsOnlyNum // false
But if you are interested in numbers, then this is a problem:
"-12.-34.".containsOnlyNum // true
Instead, you can just try casting the string to a double and see if it is a number or not
Double("1234") != nil // true, a number
Double("-1.234") != nil // true, a number
Double("A1234") != nil // false, not a number
Double("-12.-34.") != nil // false, not a number
Which is almost right unless you don't want this case:
Double("1234e2") != nil // true, a number
But you can use both checks if you don't want to allow that, or else if you are able to parse a Double from the input you can just do the cast.

Use if-let for more than one condition

I have a code that looks like so:
let myItems = presenter?.getShoppingListItems()
if myFlag.isEnabled() && myItems!.isEmpty {
//Do something
Now, I want to write this line if myFlag.isEnabled() && shoppingListItems!.isEmpty using if-let.
I tried this:
let myItems = presenter?.getShoppingListItems()
if let _ = myFlag.isEnabled(), let myItems = myItems?.isEmpty {
//Do something
And this:
let myItems = presenter?.getShoppingListItems()
if let myFlag.isEnabled(), let _ = myItems?.isEmpty {
//Do something
But it's not working. What am I missing here?
Optional binding (if let ...) is supposed to be used when you want to unwrap an optional value and bind it to an identifier. Here, you are not trying to bind anything - you are just trying to check two conditions: myFlag.isEnabled() and myItems?.isEmpty, so a regular if condition will work.
You do need to make sure that the conditions are of type Bool though, not Bool?.
Assuming yo do not want the if statement to run when myItems is nil, you can achieve this by directly comparing the optional myItems?.isEmpty with true.
if myFlag.isEnabled() && myItems?.isEmpty == true {
Alternatively, you can mix optional binding with regular Bool conditions. You can bind myItems, and check isEnabled and isEmpty, all within the same if statement:
if let myItems = presenter?.getShoppingListItems(),
myFlag.isEnabled(), myItems.isEmpty == true {
}
Or you can bind on myItems?.isEmpty, since that is an optional as well:
if let isEmpty = myItems?.isEmpty,
myFlag.isEnabled(), isEmpty {
}
If you want the if statement to also be executed when myItems is nil, you can change the condition to != false:
if myFlag.isEnabled() && myItems?.isEmpty != false {
You can try
if let items = presenter?.getShoppingListItems(), items.isEmpty, myFlag.isEnabled() { ... }

Setting variable equal to if statement condition

I have an if statement that checks to see if an array element matches a local variable.
if pinArray.contains(where: {$0.title == restaurantName})
How would I create a variable of this element?
I attempted
let thePin = pinArray.contains(where: {$0.title == restaurantName})
but this comes with "could not cast boolean to MKAnnotation".
I also tried variations of
let pins = [pinArray.indexPath.row]
let pinn = pins(where: pin.title == restaurantName) (or close to it)
mapp.selectAnnotation(thePin as! MKAnnotation, animated: true)
to no avail. What basic step am I missing?
contains(where:) returns a Bool indicating whether a match was found or not. It does not return the matched value.
So thePin is a Bool which you then attempt to force-cast to a MKAnnotation which of course crashes.
If you want the matching value, change your code to:
if let thePin = pinArray.first(where: { $0.title == restaurantName }) {
do {
mapp.selectionAnnotation(thePin, animated: true)
} catch {
}
} else {
// no match in the array
}
No need for contains at all. No need to cast (assuming pinArray is an array of MKAnnotation).

Swift-y boolean expression - case outside if/switch

To continue to the next screen, a patron must have one of two identifiers. The code I've got to do this is:
let identifier1Entered = !patron.identifier1.isEmpty
let identifier2Entered = patron.identifier2 != nil && !patron.identifier2!.isEmpty
guard identifier1Entered || identifier2Entered else { return }
But it's not Swifty, I'm force-unwrapping the optional identifier2, because I don't want to expand this to a longer, and IMO messier
var identifier2Entered = false
if let identifier2 = patron.identifier2 where !identifier2.isEmpty {
identifier2Entered = true
}
What I thought might work is just taking the expression out of the if statement, like:
let id2Entered = let identifier2 = patron.identifier2 where !identifier2.isEmpty
or
let id2Entered = case .Some(let id2) = patron.identifier2 where !id2.isEmpty
But it appears that these expressions are only allowed within if statements.
The other more Swifty solution I thought of is this:
let identifier1Entered = !patron.identifier1.isEmpty
guard let id2 = patron.identifier2 where !id2.isEmpty || identifier1Entered
else { return }
But it requires that identifier2 is not nil, which is incorrect, and as far as I know, there's no way to use optional binding with || in if or guard statements. Not to mention that I feel it's less clear and readable than the force-unwrapping.
Anyone have a clear, more Swifty solution?
Two possible solutions using optional chaining:
let identifier2Entered = patron.identifier2?.isEmpty == false
let identifier2Entered = !(patron.identifier2?.isEmpty ?? true)
If patron.identifier2 is nil then patron.identifier2?.isEmpty
evaluates to nil, and you'll get false as a result.

How to make changes to a variable inside an if statement

I'm trying to make changes to a var inside an if statement, for some reason I can not get it to change.
func checkIfFieldsEmpty()-> Bool{
var textfieldStatus:Bool!
var v = [
"name" : ""
]
for (key, value) in v {
if value == "" {
textfieldStatus = false
} else {
textfieldStatus = true
}
}
return textfieldStatus
}
That will always return false. If you want to check if the values are completely empty, then I think you want this.
for (key, value) in textfield {
if value == "" {
textfieldStatus = false
}else{
textfieldStatus = true
break
}
}
According to #fridgemagnet answer, the difference is you are calling a method which required a Dictionary parameter. But you are always setting a
var v = [ "name":""]
And you are checking the variable "v" value which should always return false and by default your "textfieldStatus" value is false. So there is no chance to change your "textfieldStatus" value. Please make sure what you exactly want.
You define v as empty, and then check if its empty. Try v = ["name": "peter"](but, it's not really what you want). When you declare var v = ..., you are clearing the previous values for v if it is defined earlier in the program.
This solution work well form me
func checkIfFieldsEmpty()-> Bool{
var v = [
"name":""
]
var textfieldStatus:Bool = true
var fielderrorCount:Int = 0
for (key, value) in v{
if value == ""{
fielderrorCount = 1
}
}
if fielderrorCount > 0{
textfieldStatus = false
}
return textfieldStatus
}