This seems like it should be trivial and it's driving me batty. This is my struct declaration:
struct ThemePic: Identifiable {
let id: Int
let pic: String
}
and this is the function with a compile error:
func themeChange(newEmojis: [String]) -> [ThemePic] {
var newTheme: [ThemePic]
var whichEmoji: Int
for x in 0..<newEmojis.count {
whichEmoji = Int.random(in: 0..<newEmojis.count)
newTheme = (x, newEmojis[whichEmoji])
}
return newTheme
}
Whether I use = or append I get pretty much the same responses:
- Operator function ' =' requires the types 'ContentView.themePic' and '(Int, String).Element' be equivalent
- Type '(Int, String)' cannot conform to 'Sequence'
It's clearly saying that my types do match, so...?
CodePudding user response:
The (or =) operator can be used to append another array to an array. It is not used to add an element to an array, like you are trying to do here. Use the append method instead.
Your array is also not an array of tuples, so you cannot add tuples such as (x, newEmojis[whichEmoji]) into it. It is an array of ThemePics. You should create a ThemePic instance using its initialiser.
var newTheme: [ThemePic] = [] // remember to initialise the array!
var whichEmoji: Int
for x in 0..<newEmojis.count {
whichEmoji = Int.random(in: 0..<newEmojis.count)
newTheme.append(ThemePic(id: x, pic: newEmojis[whichEmoji]))
}
return newTheme
This can be done in a much shorter way using map:
(0..<newEmojis.count).map { ThemePic(id: $0, pic: newEmojis.randomElement()!) }
It seems like you are trying to shuffle the newEmojis and turn them into ThemePics. If that is the case, then please note that your current approach might produce ThemePics with duplicate pics, as Int.random could return the same thing in two iterations. If that is undesirable, you can do something like:
newEmojis.shuffled().enumerated().map(ThemePic.init)
CodePudding user response:
You're getting this error because the types you are trying to combine actually don't match. Specifically:
newThemeis anArrayofthemePicvalues- The value you are trying to append to the array is not a
themePicbut a tuple:(Int, String)
There is no automatic conversion between (Int, String) and a themePic, so you need to construct a themePic out of the values you have in order to append:
newTheme.append(themePic(id: x, pic: newEmojis[whichEmoji]))
Additional notes:
Idiomatic Swift naming guidelines would have the name of the type be capitalized:
themePic→ThemePicSimilarly with your function name, which should be camelCased:
ThemeChange→themeChangeOnce you fix the above error, you'll also need to appropriately initialize
newThemebefore you can append to it:var newTheme: [ThemePic] = [] // OR var newTheme = [ThemePic]()
Combining these together:
struct ThemePic: Identifiable {
let id: Int
let pic: String
}
func themeChange(newEmojis: [String]) -> [ThemePic] {
var newTheme = [ThemePic]()
var whichEmoji: Int
for x in 0..<newEmojis.count {
whichEmoji = Int.random(in: 0..<newEmojis.count)
newTheme.append(ThemePic(id: x, pic: newEmojis[whichEmoji]))
}
return newTheme
}
@Sweeper's answer also covers how you might want to avoid manually looping altogether by using Sequence methods directly.
