How to solve "Argument type 'CustomStruct' does not conform to expected type 'Sequence'" - swift

I was trying to use the codes below to shuffle an array consisted of a simple custom struct called Card, and I get an error at cards.remove(at: randomIndex):
Error: Argument type 'Card' does not conform to expected type 'Sequence'
Here are the codes:
var cards = [Card]() // declare the array
var shuffledCards = [Card]()
for _ in cards.indices {
let randomIndex = Int(arc4random_uniform(UInt32(cards.count)))
shuffledCards += cards.remove(at: randomIndex) // error appears here
}
cards = shuffledCards
Oddly, as a contrast, the similar design works for Array<String>:
var emojiChoices = ["🦇", "😱", "🙀", "😈", "🎃", "👻", "🍭", "🍬", "🍎"]
let randomIndex = Int(arc4random_uniform(UInt32(emojiChoices.count)))
emoji[card.identifier] = emojiChoices.remove(at: randomIndex)
Should I add something the the definition of Card? If so, what should I add? Thanks!

The += operator in
shuffledCards += cards.remove(at: randomIndex)
expects a sequence of elements which should be append to the
shuffledCards array (for example another array). To append a single element, use
shuffledCards.append(cards.remove(at: randomIndex))

Related

Value of type _ cannot convert to specified type Set<> Swift

I'm trying to create a set of random exercises. I have made my struct Hashable and Equatable following the tutorial here https://medium.com/#JoyceMatos/hashable-protocols-in-swift-baf0cabeaebd and that is working fine so it's ready to be put in a Set<>.
When I use an Array to collect the workout exercises, as per below, it works fine. But when I switch to a Set<> I get an error "cannot convert value of type [_] to specified type 'Set'. What is it about 'Sets' that mean you can't map in the same way as an Array?
func generateWorkout() {
let allPossibleExercises = masterExerciseArray
let numberOfExercisesKey = Int(arc4random_uniform(4)+3)
//error triggers on the line below if I switch [WorkoutExercise]
//for Set<WorkoutExercise> (which conforms to Hashable/Equatable
let workoutSet : [WorkoutExercise] = (1...numberOfExercisesKey).map { _ in
let randomKey = Int(arc4random_uniform(UInt32(allPossibleExercises.count)))
return WorkoutExerciseGenerator( name: allPossibleExercises[randomKey].name,
maxReps: allPossibleExercises[randomKey].maxReps).generate()
}
print (workoutSet)
}
There is an answer here with a similar error message Cannot convert value of type '[_]' to specified type 'Array' but my array wouldn't be empty as in this example so I don't think this is the same root cause?
UPDATE : for anyone having the same problem, you can use Array but then simply convert the Array to a Set afterwards if the correct elements are Hashable/Equatable
If creating the array works create the array and then make the Set from the array. If all involved objects conform to Hashable this is supposed to work.
func generateWorkout() {
let allPossibleExercises = masterExerciseArray
let numberOfExercisesKey = Int(arc4random_uniform(4)+3)
let workoutArray : [WorkoutExercise] = (1...numberOfExercisesKey).map { _ in
let randomKey = Int(arc4random_uniform(UInt32(allPossibleExercises.count)))
return WorkoutExerciseGenerator( name: allPossibleExercises[randomKey].name,
maxReps: allPossibleExercises[randomKey].maxReps).generate()
}
let workoutSet = Set(workoutArray)
print (workoutSet)
}

index (of: element) does not exist

I have a really strange error. Have been learning Swift and was reading the documentation on finding the index of an object in an array here: https://developer.apple.com/reference/swift/array/1689674-index
However this method does not exist in my Xcode.
Here is an example:
var items : [TaskItem]
items = [TaskItem] ()
let rowitem = TaskItem()
rowitem.text = "helloworld"
items.append(rowitem)
//Attempting to find the index of an object
items.Index(of: rowitem)
//error - Xcode cannot find the specific func I am looking for
I have attached an image of the methods that appear and have not been able to find an answer for why this might happen anywhere.
I cannot find the use of the func index(of:)method although I know it exists!
I get the following compiler error:
ChecklistViewController.swift:186:26: Argument labels '(of:, _:)' do
not match any available overloads
ChecklistViewController.swift:186:26: Overloads for 'index' exist with
these partially matching parameter lists: (Int, offsetBy: Int),
(Self.Index, offsetBy: Self.IndexDistance)
TaskItem needs to conform to the Equatable protocol in order to use index(of:).
I am totally agree with Tim vermeulen but we can get the index of array using the below code and its working perfectly.
class Name {
var firstName:String = String()
var lastName:String = String()
var fullName:String{
return firstName+lastName
}
}
var items:[Name] = [Name]()
let rowitem = Name()
let name:Name = Name()
name.firstName = "Vala"
name.lastName = "bbbb"
items.append(rowitem)
items.append(name)
//Attempting to find the index of an object
print(items.index{$0 === name}!)

Reference to generic type 'Dictionary' requires arguments in <..> [duplicate]

let index1 = arc4random_uniform(10);
let x = array[index1];
The second line is giving following error
could not find an overload for 'subscript' that accepts the supplied arguments
let x = array[index1];
^~~~~~~~~~~~~
you have to convert the index to Int like e.g. this:
let index1: UInt32 = arc4random_uniform(10); // with the type of the value
let x = array[Int(index1)];
the Int is the proper index type rather than UInt32.
UPDATE
if you are not quiet happy to convert the index every individual time, you can also add an extension to Array with defining a new subscript for your generic index type(s), e.g. such extension would look with UInt32 like this:
extension Array {
subscript (index: UInt32) -> T {
get {
let intIndex : Int = Int(index)
return self[intIndex]
}
}
}
NOTE: I have not worked out the setter here.

Optional vs Bound value assigning var from array

I want to check if there is a value in a array and if so assign to a String using a if-left statement:
if let scoreValue = scoreValueArray[element!]{
// do something with scoreValue
}
Error: Bound value in a conditional binding must be of optional type
So tried changing the ! to ? but error persists.
Any input appreciated.
scoreValueArray is an array of strings, where a String value is appended to array if a condition is met, then array is saved to NSUserdefaults.
So element is a int which corresponds to a index in the array, bt only if the index is occupied with a String, so
scoreValueArray[element!]
could return an 'Index out of bounds', hence want to use the if-let.
Although the accepted answer clearly puts why optional binding is not available in the current implementation, it doesn't provide with a solution.
As it is shown in this answer, protocols provide an elegant way of safely checking the bounds of an array. Here's the Swift 2.0 version:
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
Which you can use like this:
let fruits = ["Apple", "Banana", "Cherry"]
if let fruit = fruits[safe: 4] {
// Do something with the fruit
}
It's not clear what type your scoreValueArray is, but for the sake of this answer, I'm going to assume it's an array of Int.
var scoreValueArray: Array<Int>
Now, if we look the definition of the Array struct, we'll find this:
struct Array<T> : MutableCollectionType, Sliceable {
// other stuff...
subscript (index: Int) -> T
// more stuff
}
So, calling the subscript method on our array (which is what we do when we say scoreValueArray) returns a non-optional. And non-optionals cannot be used in the conditional binding if let/if var statements.
We can duplicate this error message in a more simple example:
let foo: Int = 3
if let bar = foo {
// same error
}
This produces the same error. If we instead do something more like the following, we can avoid the error:
let foo: Int? = 3
if let bar = foo {
// perfectly valid
}
This is different from a dictionary, whose subscript method does return an optional (T?). A dictionary will return a value if the key passed in the subscript is found or nil if there is no value for the passed key.
We must avoid array-index-out-of-bounds exceptions in the same way we always do... by checking the array's length:
if element < scoreValueArray.count {
scoreValue = scoreValueArray[element]
}

Swift access array with index gives following error. Any idea why?

let index1 = arc4random_uniform(10);
let x = array[index1];
The second line is giving following error
could not find an overload for 'subscript' that accepts the supplied arguments
let x = array[index1];
^~~~~~~~~~~~~
you have to convert the index to Int like e.g. this:
let index1: UInt32 = arc4random_uniform(10); // with the type of the value
let x = array[Int(index1)];
the Int is the proper index type rather than UInt32.
UPDATE
if you are not quiet happy to convert the index every individual time, you can also add an extension to Array with defining a new subscript for your generic index type(s), e.g. such extension would look with UInt32 like this:
extension Array {
subscript (index: UInt32) -> T {
get {
let intIndex : Int = Int(index)
return self[intIndex]
}
}
}
NOTE: I have not worked out the setter here.