0

I've a grid UICollectionView showing a single text label in each cell. While the figure shows different attributes in each cell, I cannot work out how to store and access specific NSAttributedString.Key.foregroundColor values at the indexPath.item.

grid

For the text, I've an array of string values, which I call via the indexPath.item in cellForItemAt indexPath. But I can't figure out how to create an equivalent array of attribute values.

Model: let myText = ["Pos.1", "Main Verb", "Pos.2".... etc

Collection View datasource:

func colletionView(_ collectionView.UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CVCell", for: indexPath as! CVCell

    let text = myModel.myText[indexPath.item]
    let myAttribute = [NSAttributedString.Key.foregroundColor: UIColor.blue]
    let myAttributedText = NSAttributedString(string: text, attributes: myAttributes as [NSAttributedString.Key : Any])

    cell.label.attributedText = myAttributedText
    return cell
}

I've tried creating arrays of NSAttributedString or NSAttribtuedString.Key, but it never compiles. How do I do this so that I can get the right value at indexPath.item? or is this entirely the wrong approach?

let cellColor = [
     NSAttributedString.Key.foregroundColor: UIColor.blue
     NSAttributedString.Key.foregroundColor: UIColor.red
      ...

Ultimately, I'd like to have the data in a plist or json file or core data, but (I believe) would still need to load the data into an array (I believe) to access via indexPath.item.

I'm not very experienced, so I might be missing something quite basic.

Bhavesh Nayi
  • 705
  • 4
  • 15
DrWhat
  • 2,360
  • 5
  • 19
  • 33
  • Chante myText array type from [String] to [NSAttributedString] – RajeshKumar R Apr 30 '19 at 10:03
  • Do you want to store the color in coredata or plist? – RajeshKumar R Apr 30 '19 at 10:33
  • As a first step, I 'simply' want to create an array to use, and then when I've modeled the data within code, I will look to use a plist or coredata that will load the array. Right now - trying LorenzOliveto answer (makes sense to me). – DrWhat Apr 30 '19 at 11:26

1 Answers1

1

You have to create an array to store the colors in your model like the one you have for texts

Model:

let myText = ["Pos.1", "Main Verb", "Pos.2".... etc
let myColors = [UIColor.blue, UIColor.red, UIColor.green.... etc

and then access it like this

...
let text = myModel.myText[indexPath.item]
let color = myModel.myColors[indexPath.item]
let myAttributes: [NSAttributedString.Key : Any] = [.foregroundColor: color]
let myAttributedText = NSAttributedString(string: text, attributes: myAttributes)
...

Note that the one you posted is not an array but a Dictionary. Also, if you're only changing the text color you don't have to use NSAttributedString, you can change the label textColor property

Edit:

As per @Larme suggestion you can also create a struct to hold the data in your model so you can have only one array:

struct TextSettings {
    let text: String
    let color: UIColor
}
let myTextSettings = [TextSettings(text: "Pos.1", color: UIColor.blue),
                      TextSettings(text: "Main Verb", color: UIColor.red),
                      TextSettings(text: "Pos.2", color: UIColor.green), ...]

and use it when setting up the cell

...
let settings = myModel.myTextSettings[indexPath.item]
let myAttributes: [NSAttributedString.Key : Any] = [.foregroundColor: settings.color]
let myAttributedText = NSAttributedString(string: settings.text, attributes: myAttributes)
...
LorenzOliveto
  • 7,796
  • 1
  • 20
  • 47
  • 1
    I'd be better to have only one array and not multiple. Even better to use a custom struct to handle color and text, and make that array containing this custom struct instances. – Larme Apr 30 '19 at 10:37
  • 2
    Having one array is also a good practice, especially if you want to modify it. Imagine you want to remove the item at index 2, you need to remove the item on the other array too. If you want to sort according the text, same, you'll have to mimic that sort to the color array. It's possible, but you add extra work. – Larme Apr 30 '19 at 10:49
  • Simply brilliant - thank you. I did try the array as you have it, but using it in the dictionary WAS beyond my experience. Greatly appreciated. – DrWhat Apr 30 '19 at 14:33