3

Is there a way of creating an array of all colour objects created? So that every time a new colour is added, it is also automatically added to the array?

class Colours {
    var colourName: String
    var colourShades: [String?]


    init(colourName: String, colourShades: [String?]) {
        self.colourName = colourName
        self.colourShades = colourShades
    }


}

var red = Colours(colourName: "Red", colourShades: ["Crimson", "Cherry", "Rose"])


var blue = Colours(colourName: "blue", colourShades:["Ice", "Baby", "Royal"])

To give some context I am attempting to develop an app for IOS which includes a table of colours. Then when a user clicks on a colour it will take them to another table which has shades of that colour.

I want the array of colours so that I can automatically fill in the rows of the table, and then when a user adds a new colour it will automatically add a new row.

4 Answers 4

3

Use a static array defined in Colours to hold all colours that have been created. You can access this array as Colours.allColours from anywhere in your app.

Create a protocol called ColourWatcher and create a static delegate on Colours for a class that will be notified when a colour is added.

Have your tableView implement ColourWatcher and add itself as the delegate. Then, when a colour is added, the method newColourAdded will be called in your TableViewController and you can reload the data.

Also, I would recommend making the array of colour shades just be [String] instead of using optionals. An empty array will signify that you have no shades.

protocol ColourWatcher: class {
    func newColourAdded(colour: Colour)
}

class Colours {
    static var allColours: [Colours] = []
    static weak var delegate: ColourWatcher?

    var colourName: String
    var colourShades: [String]

    init(colourName: String, colourShades: [String]) {
        self.colourName = colourName
        self.colourShades = colourShades
        Colours.allColours.append(self)
        Colours.delegate?.newColourAdded(colour: self)
    }
}

class MyTableViewController: UIViewController, ColourWatcher {

    func viewDidLoad() {
        super.viewDidLoad()
        Colours.delegate = self
    }

    func newColourAdded(colour: Colour) {
        // reload table view or just insert a new row
        // using the passed in colour
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you, that was a massive help. I'm getting the following error in my tableView function: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = Colours.allColours[indexPath.row] return cell } Error is cannot assign value of type 'Colours' to type 'String?'. Also it only worked when I changed Colour to Colours in newColourAdded func, that right?
Colour vs. Colours was just a typo. Although your class represents just a single colour, so it should probably be named Colour. Try cell.textLabel?.text = Colours.allColours[indexPath.row].colourName.
That got rid of the error, I'll remember that in future. I now have no errors but the table displays empty, even though I have added an object to the class. I've added the number of rows and the content of the rows in the TableController - without error using the regular format. Is there something I'm missing? Sorry to be a pain I'm quite new to this and struggling to get my head around it!
You should be returning Colours.allColours.count for numberOfRowsInSection.
That is what I have, but still empty. No matter what I do the table remains empty. I've been trying everything I can think of but it doesn't appear to be making any difference :/ Thank you for your help anyway!
|
1

Is there a way of creating an array of all colour objects created? So that every time a new colour is added, it is also automatically added to the array?

You can declare one array in your class and append like this

lazy var colorList = {
  Colours()
}()

I want the array of colours so that I can automatically fill in the rows of the table, and then when a user adds a new colour it will automatically add a new row.

func addColor() {
   colorList.append(Colours(colourName: "Red", colourShades: 
   ["Crimson", "Cherry", "Rose"]))
   colorList.append(Colours(colourName: "blue", colourShades:["Ice", 
   "Baby", "Royal"]))
}

once you invoke the above method when add the color then refresh the table to appear the new color information on your table row.

To give some context I am attempting to develop an app for IOS which includes a table of colours. Then when a user clicks on a colour it will take them to another table which has shades of that colour.

Now in your tableView cellForrowatindexpath method you just need to access the above colorlist array and fetch the colorname and display on your table.

And when user tap on the cell then inside your didSelecteRowAtIndexpath method load the another class and pass the above colorList array information to that class and in order to display the shade of color access the colourShades information from the colorList array.

Comments

1

In my opinion, you want to preserve a state in the whole application.

The best way for solving your problem is creating a Singleton instance.

E.g.

class ColoursSharedModel {

    static let shared : ColoursSharedModel = ColoursSharedModel()

    var choosenColors : [Colors] = []
    private init() {}
}

Later, you should add

ColoursSharedModel.shared.choosenColors.append(self)

in your Colors' init.

Comments

1

1) Add your own notification name

extension NSNotification.Name {

    // 1
    static let NewColourAdded = NSNotification.Name(rawValue: "NewColourAdded")
}

2) Set access modifier for the object pool (static variable all) as private(set)

3) Add an initialized colours to the object pool

4) Post your notification

class Colours {

    // 2
    private(set) static var all: [Colours] = []

    var name: String
    var shades: [String]

    init(name: String, shades: [String]) {
        self.name = name
        self.shades = shades

        // 3
        Colours.all.append(self)

        // 4
        NotificationCenter.default.post(
            name: .NewColourAdded, 
            object: self
        )
    }
}

usage

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(
            self, 
            selector: #selector(self.onNewColourAdded), 
            name: .NewColourAdded, 
            object: nil
        )
    }

    func onNewColourAdded(notification: Notification) {
        guard let newColours = notification.object as? Colours else { 
            return 
        }

        // Do something
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.