2

I create a random number and assign it to the variable randomNumber. Then when I try to append the random number as an index for the emojis array to the empty array arrayOfEmojis I get the error:

'Cannot use mutating member on immutable value: 'self' is immutable'

Im also getting errors from the emoji?

import GameKit

struct EmojiProvider {
    var emojis = ["😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "☺️", "😊", "😇", "🙂", "🙃", "😉", "😌", "😍"]
    var arrayOfEmojis: [String]

    func generateEmoji() -> [String] {
        for i in 1...3 {
            var randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: emojis.count)
            arrayOfEmojis.append(emojis[randomNumber]) //error!
        }
        return arrayOfEmojis
    }
}
0

3 Answers 3

2

This happens because when you have a struct, instead of a class, you're mutating the instance itself.
Hence, when you're trying to mutate self, mark the function as mutating:

mutating func generateEmoji() -> [String] {

Also, I suggest you select a random element as follows:

return (1...3).compactMap { _ in emojis.randomElement() }

...and leave our the whole arrayOfEmojis, if you don't want to access it later.


The full code would then be:

struct EmojiProvider {
    var emojis = ["😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "☺️", "😊", "😇", "🙂", "🙃", "😉", "😌", "😍"]

    mutating func generateEmoji() -> [String] {
        return (1...3).compactMap { _ in emojis.randomElement() }
    }
}

What you could also do, is make EmojiProvider a class, instead of a struct.
You could then have the following code:

class EmojiProvider {
    var emojis = ["😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "☺️", "😊", "😇", "🙂", "🙃", "😉", "😌", "😍"]

    func generateEmoji() -> [String] {
        return (1...3).compactMap { _ in emojis.randomElement() }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

The issue is that a struct is a value type and when you modify any of its instance properties, you actually modify the struct instance itself. Hence, when you call append on arrayOfEmojis, you not only mutate arrayOfEmojis, but you mutate the EmojiProvider instance itself as well. You can get rid of the warning by marking your function as mutating.

mutating func generateEmoji() -> [String] { ...

However, it seems to me that what you are actually trying to do is simply getting 3 random elements from the array, while what your current implementation is doing is fetching 3 random elements from the array every time the generateEmoji function is called and appending those to the arrayOfEmojis array, which just keeps getting bigger and bigger as you keep calling the generateEmoji function.

To get that behaviour, change your implementation to the following:

struct EmojiProvider {
    var emojis = ["😀", "😃", "😄", "😁", "😆", "😅", "😂", "🤣", "☺️", "😊", "😇", "🙂", "🙃", "😉", "😌", "😍"]

    func generateEmoji() -> [String] {
        var arrayOfEmojis = [String]()
        for _ in 1...3 {
            let randomNumber = GKRandomSource.sharedRandom().nextInt(upperBound: emojis.count)
            arrayOfEmojis.append(emojis[randomNumber])
        }
        return arrayOfEmojis
    }
}

Or an even simpler implementation of generateEmoji using map:

func generateEmoji() -> [String] {
    return (1...3).map{_ ->String in emojis[GKRandomSource.sharedRandom().nextInt(upperBound: emojis.count)]}
}

Comments

0

Use Mutable array, you can access and delete like this

var languages: NSMutableArray = ["Swift", "C", "Objective-C"]
var randomInt = Int.random(in: 0...length)
if let text_let = languages[randomInt] as? String
{
    text = text_let
}
languages.removeObject(at: randomInt)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.