Get the content of an array of labels in Swift - ios

I'm trying to check the content of an array of labels but it not works.
To explain the program: I have 4 arrays of 4 UIlabels each one and every label contains a number in String. This function returns true if one label contains the number 16. I tried to use the function "contains" but it doesn't work because "16" it's a string and not a label.
Thanks
Example of declaration of array of labels:
Fila1 = [UILabel]()
Function Win:
func win() -> Bool {
for i in 0..<Fila1.count {
if(Fila1[i].text == "16") {
return true
} else if(Fila2[i].text == "16") {
return true
} else if(Fila3[i].text == "16") {
return true
} else if(Fila4[i].text == "16") {
return true
} else {
return false
}
}
return false
}

The issue is that you shouldn't have that else statement return false.
It should be:
if(Fila1[i].text == "16") {
return true
} else if(Fila2[i].text == "16") {
return true
} else if(Fila3[i].text == "16") {
return true
} else if(Fila4[i].text == "16") {
return true
} // end if here
You're exiting out of the loop too early. If the first element isn't what you are looking for you aren't checking the rest.

Your code is fine, you just need to remove the else condition that contains return false and the code should work as expected.

Related

check if a buttons has a set image

I am trying to have a button that checks if it has an icon if so do X other wise do Y
if button.currentImage!.isEqual(UIImage(named: "check")) {
print("X")
} else {
print("Y")
}
Since currentImage could be nil then you need to safely use ? instead of !
if button.currentImage?.isEqual(UIImage(named: "check")) ?? false {
print("X")
} else {
print("Y")
}
if it's only check if image exists then no compare
if button.currentImage != nil {
print("X")
} else {
print("Y")
}

swift - sort an array of objects by their optional boolean property without force unwrapping

I can sort this array of store objects by their 'flagship' boolean property, but how can I safely unwrap the 'flagship' property first?
let flagshipStores = self.stores.sort {
$0.flagship! && !$1.flagship!
}
let flagshipStores = self.stores.sort {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else { return false }
return flagship0 && !flagship1
}
One more approach: turn the Bool? into an Int, then compare the Ints. You get to specify how a nil value compares to non-nil values.
For instance, this sorts nil values before both false and true:
stores.sort { Int($0.flagship ?? -1) < Int($1.flagship ?? -1) }
This sorts nil values after both false and true:
stores.sort { Int($0.flagship ?? 2) < Int($1.flagship ?? 2) }
You can use the same pattern to make nil compare the same as true or the same as false. It's up to you.
Here's another approach.
You can use flatMap which will remove nil objects and unwrap those that are present. Then, the force unwrap will be safe to sort:
let flagshipStores = stores.flatMap({ return $0.flagship ? $0 : nil }).sort {
$0.flagship! && !$1.flagship!
}
This will remove stores with a nil flagship from the array.
How about:
$0.flagship == true && $1.flagship != true
The left side will succeed if the value is not nil and is true, the right side will succeed if the value is either nil or false.
As mr.Fixit pointed out on a comment, the accepted answer doesn't fully work because it doesn't take care of nils. Here is the correct answer with an extra string sample.
SWIFT 4
for a boolean sorting
let flagshipStores = self.stores.sorted(by: {
guard let flagship0 = $0.flagship, let flagship1 = $1.flagship else {
if $0.flagship == nil && $1.flagship == nil || $0.flagship != nil && $1.flagship == nil{
return true
}
else {
return false
}
}
return ($0.flagship == $1.flagship || $0.flagship == true && $1.flagship == false ? true : false)
})
for strings comparison sorting
let stores = self.stores.sorted(by: {
guard let store0 = $0.store, let store1 = $1.store else {
if $0.store == nil && $1.store == nil || $0.store != nil && $1.store == nil{
return true
}
else {
return false
}
}
return ( ($0.store)?.localizedStandardCompare($1.store!) == ComparisonResult.orderedAscending )
})
To filter nil values just use compactMap before sort
let flagshipStores = self.stores.compactMap { return $0.flagship }.sorted {
$0 && !$1
}
You could use this function to compare the Optional values without the need to unwrap.
func sortOptionalValues<T: Comparable>(lhs: T?, rhs: T?) -> Bool? {
switch (lhs != nil, rhs != nil) {
case (false, false):
return nil
case (true, false):
return true
case (false, true):
return false
case (true, true):
guard let lhs = lhs, let rhs = rhs else { return nil }
return lhs < rhs
}
}

Swift: Run code when object is within an area

I'm making a true or false game where the we have to determine if the logical expression is true or false. It's a one click game. If we click, the current true condition changes to false and vice versa. A series of logical expression will pop down the screen and when it reaches the zone, the current condition must equal to the logical expression to get a score. To verify the truth value, it checks the image of the truth value. I tried one case, where it is 'true and true' and the current condition is true, which is true. However, when it passes through the zone, the score did not increase. Where did I go wrong?
#IBAction func button_clicked(sender: UIButton) {
if (truth_click == true) {
truth_click = false
self.truth_button.image = UIImage(named: "false_button")
}
else if (truth_click == false) {
truth_click = true
self.truth_button.image = UIImage(named: "true_button")
}
}
func check_truth() {
if (truth_click == true) {
//when it reaches the zone
if (left_truth.center.y > 330 ) {
//if true and true
if ((left_truth.image == UIImage(named: "true")) && (symbol.image == UIImage(named: "and")) && (right_truth.image == UIImage(named: "true"))) {
self.score += 1
}
//if true and false
//if false and true
//if false and false
self.score_label.text = String(self.score)
}
}
if (truth_click == false) {
//when it reaches the zone
if (left_truth.center.y > 330 ) {
//if true and false
if ((left_truth.image == UIImage(named: "true")) && (symbol.image == UIImage(named: "and")) && (right_truth.image == UIImage(named: "false"))) {
self.score += 1
}
//if true and true
//if false and true
//if false and false
self.score_label.text = String(self.score)
}
}
}
Part of your problem is testing *_truth.image against new instances of UIImage(named:...). UIImage is an object. Instantiating a new UIImage creates a new object. Two objects with the same content are not equal ...without extra work.

Stuck in a loop. Very strange because the code sometimes work and sometimes just freezes

I am writing a puzzle game for an IOS. In my code I need to fill an array with some random (and non-random numbers) that will represent the main data structure.
func Random(r : Range<Int>) -> Int {
return Int(arc4random_uniform(UInt32(r.endIndex - r.startIndex))) + r.startIndex
} // function to generate random number
var arrWithColors = [Int]() // array that will hold the numbers
//function to that check if an array contains a number in a range already
func checkForNumberInArrayWithRange(r: Range <Int>, n: Int ) -> Bool {
for i in r.startIndex..<r.endIndex {
if arrWithColors[i] == n { return true }
}
return false
}
// here is the main function where i keep getting stuck. Out of let's say five times it would only work 3 or even less.
func randHexWithTag() {
var rNumber : Int = Random(0...5)
for i in 0...5 {
while (true) {
rNumber = Random(0...5)
if !checkForNumberInArrayWithRange(0...5, n: rNumber) {
break
}
}
arrWithColors[i] = rNumber
}
arrWithColors[10] = arrWithColors[1]
for i in 6...11 {
while(true) {
rNumber = Random(0...5)
if ((rNumber == arrWithColors[0] && i == 9) || (rNumber == arrWithColors[2] && i == 11)) {
continue
}
if !checkForNumberInArrayWithRange(6...11, n: rNumber) {
break
}
}
if (i != 10) {
arrWithColors[i] = rNumber
}
}
arrWithColors[13] = arrWithColors[4]
for i in 12...17 {
while(true) {
rNumber = Random(0...5)
if (rNumber == arrWithColors[3] && i == 12) || (rNumber == arrWithColors[5] && i == 14) {
continue
}
if !checkForNumberInArrayWithRange(12...17, n: rNumber) {
break
}
}
if (i != 13) {
arrWithColors[i] = rNumber
}
}
}
The above code will ALWAYS fail during the first call to checkForNumberInArrayWithRange on this line:
if arrWithColors[i] == n { return true }
That is because arrWithColors is empty, and index i is out of range

Prime number checker returns the same result each time

I'm a beginner programmer learning Swift and made a basic prime number checker. No matter what it will only give one result, instead of changing based on wether or not the number is prime. Any help would be appreciated.
#IBAction func primeCheck(sender: AnyObject) {
var numberInt = number.text.toInt()
var isPrime = true
if number != nil {
if numberInt == 1 {
isPrime = false
}
if numberInt != 1 {
for var i = 2; i < numberInt; i++ {
if numberInt! % i == 0 {
isPrime = false
} else {
isPrime = true
}
}
}
}
if isPrime == true {
result.text = "\(numberInt!) is a prime number!"
} else {
result.text = "\(numberInt!) is not a prime number!"
}
}
I have another possible solution. At first I divide by two because it cannot be a prime number. Then you loop until the number is prime or the number divided by two is less than the divider.
#IBAction func primeCheck(sender: AnyObject) {
var numberInt = number.text.toInt()
var isPrime = true
var divider = 3
if number < 2 || (number != 2 && number % 2 == 0) {
isPrime = false
}
// you only have to check to half of the number
while(isPrime == true && divider < number / 2){
isPrime = number % divider != 0
divider += 2
}
if isPrime == true {
result.text = "\(numberInt!) is a prime number!"
} else {
result.text = "\(numberInt!) is not a prime number!"
}
}
The error in your logic comes in this section:
if numberInt! % i == 0 {
isPrime = false
} else {
isPrime = true
}
At the top of your function, you initialize isPrime to be true, so in your loop you only need to look for cases that prove the number is not prime. You don't ever need to set isPrime = true again, so just drop the else condition:
if numberInt! % i == 0 {
isPrime = false
}
You actually have two functions here. One to check if a number is prime and the other to display the result. Separating these makes everything much easier to manage.
// function to check primality and return a bool
// note that this can only accept a non optional Int so there is
// no need to check whether it is valid etc...
func checkNumberIsPrime(number: Int) -> Bool {
// get rid of trivial examples to improve the speed later
if number == 2 || number == 3 {
return true
}
if number <= 1 || number%2 == 0 {
return false
}
// square root and round up to the nearest int
let squareRoot: Int = Int(ceil(sqrtf(Float(number))))
// no need to check anything above sqrt of number
// any factor above the square root will have a cofactor
// below the square root.
// don't need to check even numbers because we already checked for 2
// half the numbers checked = twice as fast :-D
for i in stride(from: 3, to: squareRoot, by: 2) {
if number % i == 0 {
return false
}
}
return true
}
// function on the button. Run the check and display results.
#IBAction func primeCheck(sender: AnyObject) {
let numberInt? = numberTextField.text.toInt() // don't call a text field "number", it's just confusing.
if let actualNumber = numberInt {
if checkNumberIsPrime(actualNumber) {
resultLabel.text = "\(actualNumber) is a prime number!" // don't call a label "result" call it "resultLabel". Don't confuse things.
} else {
resultLabel.text = "\(actualNumber) is not a prime number!"
}
} else {
resultLabel.text = "'\(numberTextField.text)' is not a number!"
}
}
It makes it all much easy to read and maintain.
You have to break out of the loop after you find that the number is divisble by another number. Also for prime check you only have to check the divisibility till the square root of the number.
You can also use optional binding to extract numberInt and check for nil. That's the swift way.
#IBAction func primeCheck(sender: AnyObject) {
var isPrime = true
if let numberInt = number.text.toInt() {
if numberInt == 1 {
isPrime = false /
}
else // Add else because you dont have to execute code below if number is 1
{
if numberInt != 1 {
for var i = 2; i * i <= numberInt; i++ { // Only check till squareroot
if numberInt % i == 0 {
isPrime = false
break // Break out of loop if number is divisible.
} // Don't need else condition because isPrime is initialised as true.
}
}
}
if isPrime {
result.text = "\(numberInt) is a prime number!"
} else {
result.text = "\(numberInt) is not a prime number!"
}
}
}
Reason for square root check : Why do we check up to the square root of a prime number to determine if it is prime?
You can refine the code further by refactoring the prime check into a separate function.
func isPrime(number:Int) -> Bool
{
if number == 1 {
return false
}
else
{
if number != 1 {
for var i = 2; i * i <= numberInt; i++ {
if numberInt % i == 0 {
return false
}
}
}
}
return true
}
#IBAction func primeCheck(sender: AnyObject) {
if let numberInt = number.text.toInt() {
if isPrime(numberInt) {
result.text = "\(numberInt) is a prime number!"
} else {
result.text = "\(numberInt) is not a prime number!"
}
}
}
Well i don't know about swift, but maybe this is wrecking your code:
if numberInt! <<
To do a faster algorithm you could just search for divisors from 2 to sqrt(numberInt). (Theorem)

Resources