Reputation: 353
I have a colours array and I am trying to get a random colour from it without getting the same two colours in a row and came across an error for previousNumber = randomNumber
saying Cannot assign to 'previousNumber' in 'self'
var previousNumber: UInt32?
func generateRandomNumber() -> Int {
var coloursArrayLength = UInt32(coloursArray.count)
var randomNumber = arc4random_uniform(coloursArrayLength)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(coloursArrayLength)
}
previousNumber = randomNumber
var randomNumberInt = Int(randomNumber)
return randomNumberInt
}
How do I fix this?
Upvotes: 2
Views: 1216
Reputation: 40973
I am guessing your function is actually inside a struct not shown in the code snippet, and the problem is you haven’t declared the function as mutating
(i.e. the function can only be called on structs declared with let
not var
because it mutates self).
I’d also suggest breaking out the logic for generating the random number into a separate function for clarity and also to cut down on needing var
so much:
func generateRandom(#upTo: UInt32, #notRepeatOf: UInt32?) -> UInt32 {
// bear in mind though that you might need to handle if your coloursArray has one entry...
precondition(upTo > 1 || notRepeatOf == nil , "avoid infinite loop")
while true {
let candidate = arc4random_uniform(upTo)
if candidate != notRepeatOf { return candidate }
}
}
struct S {
var previousNumber: UInt32? = nil
let coloursArray = [1,2,3,4]
// note mutating keyword, fixes the "cannot
// assign to self.previousNumber" error
mutating func generateRandomNumber() -> Int {
let newNumber = generateRandom(upTo: UInt32(coloursArray.count), notRepeatOf: previousNumber)
previousNumber = newNumber
return Int(newNumber)
}
}
// if you declare the struct with let,
let a = S()
// it won’t let you call mutating funcs
// "Immutable value of type 'S' only has mutating members named 'generateRandomNumber'"
a.generateRandomNumber()
// have to declare with var
var b = S()
b.generateRandomNumber()
Upvotes: 7