How to make changes to a variable inside an if statement - swift

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
}

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.

Change value of variable by reference

Hi I have 4 variables and I want to refer to one of them depending on some conditions, my current code looks as follows:
switch color {
case .Azul:
botonACambiar.tintColor = colores.salidaAzul
if backTees == true {
if option == 1{self.colorHcpBackTees1 = .Azul} else{self.colorHcpBackTees2 = .Azul}
} else {
if option == 1{self.colorHcpFrontTees1 = .Azul} else{self.colorHcpFrontTees2 = .Azul}
}
...
...
case . Cafe:
botonACambiar.tintColor = colores.salidaMarron
if backTees == true {
if option == 1{self.colorHcpBackTees1 = .Cafe} else{self.colorHcpBackTees2 = .Cafe}
} else {
if option == 1{self.colorHcpFrontTees1 = .Cafe} else{self.colorHcpFrontTees2 = .Cafe}
}
}
I have around 8 options, and as you can see it gets kind of messy.
So far I only have 4 different variables that i might manipulate:
Option 1 & 2 for FrontTees & option 1 & 2 for BackTees, but in the future the app might support more options and more colors for front and back tees.
This 4 values are saved in the app and because of this I need to keep track of them individually, thus I have the four variables:
var colorHcpBackTees1: ColoresDeSalidas = .Negra
var colorHcpBackTees2: ColoresDeSalidas = .Blanca
var colorHcpFrontTees1: ColoresDeSalidas = .Roja
var colorHcpFrontTees2: ColoresDeSalidas = .Blanca
Each with their default values, it would be nice to have a way of initializing a reference variable in such a way that I could do something like:
var choice: ColoresDeSalidas{
if backTees && option == 1 { return self.colorHcpBackTees1}
if backTees && option == 2 { return self.colorHcpBackTees2}
if !backTees && option == 1 { return self.colorHcpFrontTees1}
if !backTees && option == 2 { return self.colorHcpFrontTees2}
}
And simply use the variable choice to manipulate the value of the right variable
You can accomplish this using a ReferenceWritableKeyPath.
What is a ReferenceWritableKeyPath?
Think of it as a precise description of a property in a class or struct. A real world example would be The Empire State Building instead of the address which would be 20 W 34th St, New York, NY 10001. You could tell either one to a cab driver and she could take you there.
A ReferenceWritableKeyPath is a generic type. You need to specify the class or struct name and the type of the variable you will be accessing. So your choice variable would be a ReferenceWritableKeyPath<YourClass,ColoresDeSalidas>.
Here is a standalone example:
enum ColoresDeSalidas : String {
case Negra
case Blanca
case Roja
case Azul
case Verde
}
class Foo {
var backTees = false
var option = 1
var colorHcpBackTees1: ColoresDeSalidas = .Negra
var colorHcpBackTees2: ColoresDeSalidas = .Blanca
var colorHcpFrontTees1: ColoresDeSalidas = .Roja
var colorHcpFrontTees2: ColoresDeSalidas = .Blanca
var choice: ReferenceWritableKeyPath<Foo,ColoresDeSalidas> {
if backTees && option == 1 { return \.colorHcpBackTees1 }
if backTees && option == 2 { return \.colorHcpBackTees2 }
if !backTees && option == 1 { return \.colorHcpFrontTees1 }
if !backTees && option == 2 { return \.colorHcpFrontTees2 }
fatalError("We were supposed to return a keyPath for choice")
}
func test() {
backTees = true
option = 2
print("Before: \(self.colorHcpBackTees2)")
// Now update the correct property using the choice KeyPath
self[keyPath: choice] = .Azul
print("After: \(self.colorHcpBackTees2)")
backTees = false
option = 1
// Assign it to another variable, just to show you can
let choiceFront1 = choice
option = 2
// choiceFront1 still refers to !backTees and option 1
// even though option and choice have changed
print("colorHcpFrontTees1 = \(self[keyPath: choiceFront1])")
colorHcpFrontTees1 = .Verde
print("colorHcpFrontTees1 = \(self[keyPath: choiceFront1])")
}
}
Run the test:
Foo().test()
Output:
Before: Blanca
After: Azul
colorHcpFrontTees1 = Roja
colorHcpFrontTees1 = Verde
To clean the code you could wrap the logic for initialising the properties within the enum itself.
extension ColoresDeSalidas {
init?(isBackTee: Bool, option: Int) {
switch (isBackTee, option) {
case (true, 1): self = .colorHcpBackTees1
case (true, 2(: self = .colorHcpBackTees2
case (false, 1): self = .colorHcpFrontTees1
case (false, 2): self = .colorHcpFrontTees2
default: return nil //or assign a default and make non-failable
}
And then you can initialise / update with:
let myVar = ColoresDeSalidas(isBackTee: true, option: 1)

Swift: Checking if a member exist in a struct

For the following code, how can I check if a member "b" or "f" exist for myArray?
struct example {
var a: String!
var b: Bool!
var c: Bool!
var d: String!
}
var myArray = [example]!
For example, if I check if member "f" exists, I would like something to return "false" or "nil"; and if I check if "b" exists, I would like to receive "true".
Thanks!
Unlike Objective-C, Swift does not have the dynamic mechanisms to do things like this. So the answer is that no, you cannot check for members by name in this way, unless you are working with members of an NSObject subclass which are marked with the #objc attribute.
Using Mirror.
let example = Example()
let containsB = Mirror(reflecting: example).children.contains { $0.0 == "b" } // true
let containsF = Mirror(reflecting: example).children.contains { $0.0 == "f" } // false
let examples = [Example(), Example(), Example()]
let containsA = examples.filter {
Mirror(reflecting: $0).children.contains { $0.0 == "a" }
}.isEmpty == false // true
As others have commented, there are other problems with your example, but assuming you know and are just throwing out a quick and dirty sample to illustrate your question, you could do something a bit like this:
if let bExists = myArray.b {
return true
} else if let fExists = myArray.f {
return false // or return nil, or whatever you want to do if `f exists.
}

Checking values within tuple that contains only booleans

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.

Nested Swift Dictionaries

I want to initialize a dictionary with a dictionary nested inside like this:
var a = [Int:[Int:Float]]()
a[1][2] = 12
But I get an error:
(Int:[Int:Float]) does not have a member named 'subscript'
I've hacked at a variety of other approaches, all of them running into some kind of issue.
Any idea why this doesn't work?
You can create your own 2D dictionary like this:
struct Dict2D<X:Hashable,Y:Hashable,V> {
var values = [X:[Y:V]]()
subscript (x:X, y:Y)->V? {
get { return values[x]?[y] }
set {
if values[x] == nil {
values[x] = [Y:V]()
}
values[x]![y] = newValue
}
}
}
var a = Dict2D<Int,Int,Float>()
a[1,2] = 12
println(a[1,2]) // Optional(12.0)
println(a[0,2]) // nil
The point is you access the element via a[x,y] instead of a[x][y] or a[x]?[y].
It's giving you that error because your first subscript returns an optional so it may return a dictionary or nil. In the case that it returns nil the second subscript would be invalid. You can force it to unwrap the optional value by using an exlamation point.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]![2]
If you aren't positive that a[1] is non-nil you may want to safely unwrap with a question mark instead.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]?[2]
You can also assign using this method. (As of Beta 5)
var a = [Int:[Int:Float]]()
a[1] = [Int: Float]()
a[1]?[2] = 12.0
a[1]?[2] //12.0
Another way to do it is with an extension to the standard dictionary:
extension Dictionary {
mutating func updateValueForKey(key: Key, updater: ((previousValue: Value?) -> Value)) {
let previousValue = self[key]
self[key] = updater(previousValue: previousValue)
}
}
Example:
var a = [Int:[Int:Float]]()
a.updateValueForKey(1) { nestedDict in
var nestedDict = nestedDict ?? [Int:Float]()
nestedDict[2] = 12
return nestedDict
}