Valid number between two numbers in a textfield - ios

Allowing only a valid number between x and y to be entered. And display an error message if an invalid number is entered.
I messed around with some if statement and put said x and y numbers in a range, but I don't know how to make that work and display that in lets say a label for example.
I expect the output to be display in a label when a valid number is entered in a text field, when button is pushed. And an error display in a label when an invalid number is enter when the button is pushed.

You can achieve that with the help of several ways. following are can be the best way to get into that.
func validateNumber() {
yourLbl.text = checkNumber(startNumber: 10, endNumber: 20, numberToCheck: 11)
}
I have created a method which is having several ways to do so... you can keep the best one at your convenient
func checkNumber(startNumber: Int, endNumber: Int, numberToCheck: Int) -> String {
//WITH THE HELP OF `~=` operator
if startNumber...endNumber ~= numberToCheck {
return "\(numberToCheck) is within the range of \(startNumber)-\(endNumber)"
} else {
return "\(numberToCheck) is not within the range of \(startNumber)-\(endNumber)"
}
//WITH THE HELP OF .contains mathod
if (startNumber...endNumber).contains(numberToCheck) {
return "\(numberToCheck) is within the range of \(startNumber)-\(endNumber)"
} else {
return "\(numberToCheck) is not within the range of \(startNumber)-\(endNumber)"
}
//WITH THE HELP OF switch statement
switch numberToCheck {
case startNumber...endNumber:
return "\(numberToCheck) is within the range of \(startNumber)-\(endNumber)"
default:
return "\(numberToCheck) is not within the range of \(startNumber)-\(endNumber)"
}
//WITH THE HELP OF if statement
if case startNumber...endNumber = numberToCheck {
return "\(numberToCheck) is within the range of \(startNumber)-\(endNumber)"
} else {
return "\(numberToCheck) is not within the range of \(startNumber)-\(endNumber)"
}
}

check if a range contains a value in Swift
1. Pattern matching operator ~=
func validateRange(_ value : Int) {
if 2..<50 ~= value {
//in range
} else {
// displayLabel.text = "Error message"
}
}
2. .contains method
func validateRange(_ value : Int) {
if (2..<50).contains(value) {
//in range
} else {
// displayLabel.text = "Error message"
}
}
Example :
#IBAction func tappedOnOkButton(_ sender: Any) {
if let value = Int(numberTextField.text) {
validateRange(value)
} else {
// error
}
}

Related

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 {
}

Exit from loop after finding the first positive element in swift

So, need you help, I have loops, where I'd like to find first positive element and it will be text of label and exit from all loops, but every time I get last element:
for j in getArrayOfAllTimes[i].timeForGetDifference()
{
switch j - timeNow() {
case let x where x > 0:
nextTimeLabel.text = String(j - timeNow())
break
default:
break
}
}
How get first element > 0?
The first(where:) method of Array
Instead of explicitly breaking out of a loop when a first element that fulfills som predicate is found, you could simply make use of the Array method first(where:).
Since you haven't provided us with a minimal, complete and verifiable example (which you should) we'll construct such an example:
/* Example setup */
struct Foo: CustomStringConvertible {
private let bar: Int
init(_ bar: Int) { self.bar = bar }
func timeForGetDifference() -> Int {
return bar
}
var description: String {
return String(bar)
}
}
func timeNow() -> Int { return 10 }
let getArrayOfAllTimes = [Foo(6), Foo(2), Foo(9), Foo(4), Foo(11), Foo(3), Foo(13)]
// nextTimeLabel: some UILabel
For the example as per above, we could set the text property of the nextTimeLabel as follows, using first(where:) to find the first element fulfilling our predicate, given that it exists (otherwise; will return nil in which case we will not enter the optional binding block below).
if let firstNonNegativeFoo = getArrayOfAllTimes
.first(where: { $0.timeForGetDifference() - timeNow() > 0 }) {
nextTimeLabel.text = String(describing: firstNonNegativeFoo) // 11
}
As to why your own approach does not work as intended: a break statement within a case of a switch statement will simply end the execution of the switch statement (not the loop which is one level above the switch statement.
From the Language Reference - Statements:
Break Statement
A break statement ends program execution of a loop, an if statement,
or a switch statement.
In you case, you've added the break statements as the last statements of each case: here, particularly, the break has truly no effect (since the switch statement would break out anyway, after exiting the case which it entered).
for i in 1...3 {
switch i {
case is Int: print(i); break // redundant 'break'
case _: ()
}
} // 1 2 3
// ... the same
for i in 1...3 {
switch i {
case is Int: print(i)
case _: ()
}
} // 1 2 3
for j in getArrayOfAllTimes[i].timeForGetDifference() {
bool a = NO;
switch j - timeNow() {
case let x where x > 0:
a = YES
nextTimeLabel.text = String(j - timeNow())
break
default:
break
}
if a == YES {
break;
}
}

Swift call random function

I got 3 different functions and I want to call one of these randomly.
if Int(ball.position.y) > maxIndexY! {
let randomFunc = [self.firstFunction(), self.secondFunction(), self.thirdFunction()]
let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count)))
return randomFunc[randomResult]
}
With this code I call all functions, and the order is always the same. What can I do to just call one of these?
The reason the three functions are called (and in the same order) is since you are causing them to be called when you put them in the array.
This:
let randomFunc = [self.firstFunction(), self.secondFunction(), self.thirdFunction()]
Stores the return value of each function in the array since you are invoking them (by adding the '()').
So at this point randomFunc contains the return values rather than the function closures
Instead just store the functions themselves with:
[self.firstFunction, self.secondFunction, self.thirdFunction]
Now if you want to call the selected method do not return its closure but invoke it:
//return randomFunc[randomResult] // This will return the function closure
randomFunc[randomResult]() // This will execute the selected function
if Int(ball.position.y) > maxIndexY! {
let randomNumber = Int.random(in: 0...2)
if randomNumber == 0 {
firstFunction()
} else if randomNumber == 1 {
secondFunction()
} else if randomNumber == 2 {
thirdFunction()
}
}
I expect it should work
if Int(ball.position.y) > maxIndexY! {
let randomFunc = [self.firstFunction, self.secondFunction, self.thirdFunction]
let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count)))
return randomFunc[randomResult]()
}

Swift switch statement for matching substrings of a String

Im trying to ask for some values from a variable.
The variable is going to have the description of the weather and i want to ask for specific words in order to show different images (like a sun, rain or so)
The thing is i have code like this:
if self.descriptionWeather.description.rangeOfString("Clear") != nil
{
self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("rain") != nil
{
self.imageWeather.image = self.soleadoImage
}
if self.descriptionWeather.description.rangeOfString("broken clouds") != nil
{
self.imageWeather.image = self.nubladoImage
}
Because when i tried to add an "OR" condition xcode gives me some weird errors.
Is it possible to do a swich sentence with that? Or anyone knows how to do add an OR condition to the if clause?
I had a similar problem today and realized this question hasn't been updated since Swift 1! Here's how I solved it in Swift 4:
switch self.descriptionWeather.description {
case let str where str.contains("Clear"):
print("clear")
case let str where str.contains("rain"):
print("rain")
case let str where str.contains("broken clouds"):
print("broken clouds")
default:
break
}
Swift 5 Solution
func weatherImage(for identifier: String) -> UIImage? {
switch identifier {
case _ where identifier.contains("Clear"),
_ where identifier.contains("rain"):
return self.soleadoImage
case _ where identifier.contains("broken clouds"):
return self.nubladoImage
default: return nil
}
}
You can do this with a switch statement using value binding and a where clause. But convert the string to lowercase first!
var desc = "Going to be clear and bright tomorrow"
switch desc.lowercaseString as NSString {
case let x where x.rangeOfString("clear").length != 0:
println("clear")
case let x where x.rangeOfString("cloudy").length != 0:
println("cloudy")
default:
println("no match")
}
// prints "clear"
Swift language has two kinds of OR operators - the bitwise ones | (single vertical line), and the logical ones || (double vertical line). In this situation you need a logical OR:
if self.descriptionWeather.description.rangeOfString("Clear") != nil || self.descriptionWeather.description.rangeOfString("clear") != nil {
self.imageWeather.image = self.soleadoImage
}
Unlike Objective-C where you could get away with a bitwise OR in exchange for getting a slightly different run-time semantic, Swift requires a logical OR in the expression above.
If you do this a lot, you can implement a custom ~= operator that defines sub-string matching. It lends itself to this nice syntax:
switch "abcdefghi".substrings {
case "def": // calls `"def" ~= "abcdefghi".substrings`
print("Found substring: def")
case "some other potential substring":
print("Found \"some other potential substring\"")
default: print("No substring matches found")
}
Implementation:
import Foundation
public struct SubstringMatchSource {
private let wrapped: String
public init(wrapping wrapped: String) {
self.wrapped = wrapped
}
public func contains(_ substring: String) -> Bool {
return self.wrapped.contains(substring)
}
public static func ~= (substring: String, source: SubstringMatchSource) -> Bool {
return source.contains(substring)
}
}
extension String {
var substrings: SubstringMatchSource {
return SubstringMatchSource(wrapping: self)
}
}
I'd recommend using a dictionary instead, as a mapping between the substring you're searching for and the corresponding image:
func image(for weatherString: String) -> UIImage? {
let imageMapping = [
"Clear": self.soleadoImage,
"rain": self.soleadoImage,
"broken clouds": self.nubladoImage]
return imageMapping.first { weatherString.contains($0.key) }?.value
}
A dictionary gives you flexibility, adding new mappings is easy to do.
This link also describes overloading operator ~= which is actually used by the switch statement for matching cases to allow you to match regular expressions.

Immutable array on a var?

I am getting the error:
Immutable value of type 'Array Character>' only has mutating members of name removeAtIndex()
The array should have contents because that removeAtIndex line is in a loop who's condition is if the count > 1
func evaluatePostFix(expression:Array<Character>) -> Character
{
var stack:Array<Character> = []
var count = -1 // Start at -1 to make up for 0 indexing
if expression.count == 0 {
return "X"
}
while expression.count > 1 {
if expression.count == 1 {
let answer = expression[0]
return answer
}
var expressionTokenAsString:String = String(expression[0])
if let number = expressionTokenAsString.toInt() {
stack.append(expression[0])
expression.removeAtIndex(0)
count++
} else { // Capture token, remove lefthand and righthand, solve, push result
var token = expression(count + 1)
var rightHand = stack(count)
var leftHand = stack(count - 1)
stack.removeAtIndex(count)
stack.removeAtIndex(count - 1)
stack.append(evaluateSubExpression(leftHand, rightHand, token))
}
}
}
Anyone have any idea as to why this is? Thanks!
Because all function parameters are implicitly passed by value as "let", and hence are constant within the function, no matter what they were outside the function.
To modify the value within the function (which won't affect the value on return), you can explicitly use var:
func evaluatePostFix(var expression:Array<Character>) -> Character {
...
}

Resources