Search code examples
iosuitableviewuicollectionviewnsattributedstringnsattributedstringkey

How to store and access an 'array' of NSAttributedString.Key.foregroundColor values


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.


Solution

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