contextual type cgfloat cannot be used with array literal - swift

I'm using UIImage+Gradient.swift file to add gradient to my label, but I get this error:
contextual type cgfloat cannot be used with array literal
I've reviewed some FAQ Q&A but I'm still confused.
Here is the code:
let components = colors.reduce([]) { (currentResult: [CGFloat], currentColor: UIColor) -> [CGFloat] in
var result = currentResult
let numberOfComponents = currentColor.cgColor.numberOfComponents
let components = currentColor.cgColor.components
if numberOfComponents == 2 {
result.append([components?[0], components?[0], components?[0], components?[1]])
} else {
result.append([components?[0], components?[1], components?[2], components?[3]])
}
return result
}
Lines which are giving error are these:
result.append([components?[0], components?[0], components?[0], components?[1]])
result.append([components?[0], components?[1], components?[2], components?[3]])

This error has to do with trying to make a variable that is not an array be set to an array. For example this would produce a similar error:
var myFavSnacks:String = ["Apples","Grasses","Carrots"] //gives similar error
In your case, it thinks you want to add an array of CGFloats to one index in your array, rather than adding a number of CGFloats to your array.
To add multiple items to an array at once use contentsOf: like this:
colors.append(contentsOf: ["red", "blue"])
//adds strings "red" and "blue" to an existing array of strings called colors
From documentation available here:
https://developer.apple.com/reference/swift/array

Related

Filter / Search function on Array of Structs, to display within tableView

I have created my own Struct object, that is populated from the Photos framework with each "moment" an image was contained in, and other metadata.
struct MomentImage {
var momentNo : Int
var index : Int
var image : UIImage
}
I would like to populate a tableView, split with:
Sections, which map to momentNo
Cells, which map to index
In tableView(cellForRowAt indexPath), I have printed out:
print("location: \(indexPath.section) and \(indexPath.row)")
But the Section value only ever prints "0". I expected my print statements to occur through all the sections in this table (with my test data, this is actually 13 sections)
How do I filter / retrieve this object at these 2 indices from my array of var moments = [MomentImage]...
Using array.filter { } seems the most obvious way. How do I pass in a 2nd property to check (i.e. momentNo AND index) within the same call?
let filteredassets = assets.filter { $0.momentNo == indexPath.section }
is my current code.
Note, the images need to be encodable, hence extracting from the PHImageManager into a distinct UIImage within a Struct that should itself be encodable.
As provided by #Vicaren, applying a && after the 1st parameter converts into to a 2-property IF AND statement
$0 is still available to select, simply choose another available property to test.
My own example results in:
let filteredassets = assets.filter { $0.momentNo == indexPath.section && $0.index == indexPath.row }

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)
}

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

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))

Nested array error [duplicate]

This question already has answers here:
Arrays and Swift
(3 answers)
Closed 5 years ago.
I know this is a really newbie question but it has thrown me for days and I can't seem to find a solution that I actually understand.
I am trying to make a nested array to store latitude and longitude, however it Xcode/playground throws a EXC_BAD_INSTRUCTION error.
I want to declare, initialise and print the contents of an array. What am I doing wrong?
var arrayLocations:[[Float]] = []
arrayLocations[0] = [27.1750199, 78.0399665]
print("\(arrayLocations[0][0]) and \(arrayLocations[0][1])")
You cannot assign a value to index 0 because there is no index 0 if the array is empty.
You have to append or insert the item:
arrayLocations.append([27.1750199, 78.0399665])
You cannot assign value into 0 position because index 0 is empty.
You can do this in following ways -
With initial value -
var arrayLocations:[[Float]] = [[0.00,0.00]]
arrayLocations[0] = [27.1750199, 78.0399665]
print("\(arrayLocations[0][0]) and \(arrayLocations[0][1])")
Otherwise you can do this using append or insert as vadian's answer.
As vadian said on his answer
You cannot assign a value to index 0 because there is no index 0 if
the array is empty.
You have to append or insert the item:
arrayLocations.append([27.1750199, 78.0399665])
I suggest that you make use of this Collection extension so that your code won't crash often
extension Collection where Indices.Iterator.Element == Index {
/// Returns the element at the specified index if it is within bounds, otherwise nil.
subscript (safe index: Index) -> Generator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
By using this you could just use if let blocks
Sample:
if let aLocation = arrayLocations[safe: 0] {
aLocation = [27.1750199, 78.0399665]
}
This ensures that even if you try to access an object of index 0 your code won't crash.
Suggestion:
Note: This suggestion is not part of the answer, but rather something to improve your code.
It looks like you're trying to create an array of latitude and longitude. Using an array for the latitude and longitude object isn't very wise. I suggest that you create an object instead, it can be a struct or a typeAlias
For example:
struct CoordinateStruct {
var longitude: Float
var latitude: Float
}
/* or */
typealias CoordinateTypeAlias = (latitude: Float, longitude: Float)
/************************* */
// Your code would then look like this
var arrayLocations:[CoordinateStruct] = []
arrayLocations.append(CoordinateStruct(longitude: 27.12312312, latitude: 78.123123))
/* or */
var arrayLocations:[CoordinateTypeAlias] = []
arrayLocations.append((27.12312312, 78.123123))
// Which would make accessing them very easy and readable, like this.
if let aLocation = arrayLocations[safe: 0] {
print(aLocation.longitude)
print(aLocation.latitude)
// instead of this
print(aLocation[0]) // a person who reads your code won't understand this
print(aLocation[1]) // a person who reads your code won't understand this
}

Why the fatal error: Array index out of range show when print array in Swift?

I am new in Swift. I create a node swift file to store the node information. And the other group swift file is a group which store the all node.
The code of Node.swift is like the following:
class Node {
var id:UInt8=0
var type:Int=0
var name:String=""
var bdAddr:NSUUID!
//The node private packet counter
var nodePktNum:Int=0
}
The code of Group.swift is like the following:
class Group {
var mLedDevice:[LedDevice]? = [LedDevice]()
class LedDevice {
var node :Node?
var rssi :Int?
}
func allocateNode()
{
print("mLedDevice![0].node = \(mLedDevice![0].node))")
}
}
When I try call function (allocateNode) and try to print mLedDevice![0].node) via print("mLedDevice![0].node = \(mLedDevice![0].node))")
It show the error fatal error: Array index out of range.
Did I missing something for initialize of var mLedDevice:[LedDevice]? = [LedDevice]() ?
Thanks in advance.
===================================EDIT=================================
I want to add the item into array , so I create a parameter like let let leddevice : LedDevice , and try to give it some value. And add the leddevice into array mLedDevice. But it show constant 'leddevice' used before being initialized.
How to give the init value for let leddevice : LedDevice ?
func allocateNode()
{
let leddevice : LedDevice
leddevice.node?.id = UInt8(0)
leddevice.node!.bdAddr = NodeUUID
mLedDevice?.append(leddevice)
}
The only thing I can think about that can cause this is that the array is empty i.e. you are attempting to access index 0 of that array but that doesn't exist.
Try the following and it may give you an insight on how to solve it after seeing the content of the array:
print("mLedDevice = \(mLedDevice))")
In other words you are instantiating an array with no elements in it.
In your line of code
var mLedDevice:[LedDevice]? = [LedDevice]()
You are only initializing an empty array. What you are trying afterwards is to access the first element, of an empty array, which is out of bounds.
Before your print statement, you will need to add an item to your array
var ledDevice = LedDevice()
mLedDevice.append(ledDevice)
And then your print statement would not give you any errors.
UPDATED: Answer for the added question
let leddevice : LedDevice is defining a constant of type LedDevice but is not yet initialized, and then it is being used in the next lines of code. You should replace it with
let leddevice = LedDevice()
Which will also initialize the variable.
Note: If you have any further questions, you should write a new question for that.
Note2: Have you read any guides about initialization?