I’m trying to consolidate the stuff I’ve covered in iOS Foundations Course, by making my own basic apps, before I move on to Databases.
I want to create an app that will give print instructions to the user. Those instructions can be issued by one of three functions.
I figured the easiest way of doing this is to assign each function into an array, and then use .randomElement to call one of the functions randomly each time
Sure you can store functions in an array. In Swift, functions are first-class objects, so you can pass them around like data values. Just like you can assign a function to a variable and call it, you can stick functions in an array and call them. You just have to declare the array’s type to be the function signature and then all the functions you put in the array have to have the same signature.
Try this in a playground to see for yourself:
import Foundation
var funcArray: [() -> Void] = []
func func1() {
print("running func1")
}
func func2() {
print("running func2")
}
func func3() {
print("running func3")
}
funcArray.append(func1)
funcArray.append(func2)
funcArray.append(func3)
//this works for closures as well, as long as they match the function signature:
funcArray.append( { print("it's a closure!") } )
for ff in funcArray {
ff()
}
funcArray.forEach { ff in
ff()
}
funcArray.forEach { $0() }
Note the three different ways you can loop through your array and call the contained functions.
You can even return a random function from your array, like so:
// but note that we have to unwrap since randomElement() returns an Optional
funcArray.randomElement()?()
And here is a very, very contrived example of how you could use functions stored in an array.
//all of our validation functions have the signature (String) -> Bool
// so we can store them in an array together
func hasUppercase(_ password: String) -> Bool {
return password.rangeOfCharacter(from: .uppercaseLetters) != nil
}
func hasLowercase(_ password: String) -> Bool {
return password.rangeOfCharacter(from: .lowercaseLetters) != nil
}
func hasNumber(_ password: String) -> Bool {
return password.rangeOfCharacter(from: .decimalDigits) != nil
}
func hasPunctuation(_ password: String) -> Bool {
return password.rangeOfCharacter(from: .punctuationCharacters) != nil
}
let usernameValidationRules = [hasUppercase, hasLowercase, hasNumber]
let username = "GeorgeJetson1"
var validUsername = usernameValidationRules.allSatisfy { $0(username) }
print("username is valid? \(validUsername)")
//"GeorgeJetson1" is a valid username because it returns true from all the functions
// in usernameValidationRules
let passwordValidationRules = [hasUppercase, hasLowercase, hasNumber, hasPunctuation]
let password = "HGytyhg65"
var validPassword = passwordValidationRules.allSatisfy { $0(password) }
print("password is valid? \(validPassword)")
//"HGytyhg65" is not a valid username because it returns false from the hasPunctuation function
// in passwordValidationRules
The move is done. sorry for posting in the wrong place
Blockquote A function is not a data type.
that’s where I was stumped. I was hoping it was possible to store the function name as a string in the array and then somehow call it up by appending the string to something, but I guess not. I think this is sort of what you’re suggesting with the switch statement. I’ll look into doing that.
thank you. I’m going to try this method, and then see if I can do it by storing an array of ints and then create a switch statement, like described by Mikaela above. The more ways I do it, the more proficient I will get, I think…