简体   繁体   中英

Listen for updates in the data model array when one of its properties changes

I have a custom UITableViewCell which has a data model array, and a UILabel as this:

class ItemCustomizationCollectionViewCell: UITableViewCell {

    var customizationData: CustomizationData?

    let priceLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 18)
        label.textAlignment = .left
        label.textColor = UIColor.gray
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }() 

    //other init and constraints
}

Now, the CustomizationData looks like this:

class CustomizationData {
    let title: String
    var customizationOptions: [PickerOption]
    var choosenOption: PickerOption?

    init(title: String, customizationOptions: [PickerOption], choosenOption: PickerOption?) {
        self.title = title
        self.customizationOptions = customizationOptions
        self.choosenOption = choosenOption
    }
}

and the PickerOption is:

class PickerOption {
    let title: String
    let price: String

    init(title: String, price: String) {
        self.title = title
        self.price = price
    }
}

My Question is:

I want to listen to customizationData's choosenOption gets set, and get the title to change the UILabel 's text to the choosenOption's price.

I tried to add a didSet to the customizationData but it's not being called as one of its properties is changing. Not the customizationData itself.

What you can do is possible, but to trigger a didSet customizationOptions of you need to change its value, basically in 2 ways:

  • if customizationOptions is a reference type, you need to change it with another reference
  • if customizationOptions is a value type such as an Array , the didSet should be called also if you change a value inside it, because the array change the struct completely.

To understand better here is an example.
Using a value type:

class Mine {
    var list: [String] = ["Hello"] {
        didSet {
            print("Array changed \(list)")
        }
    }
}

var mine = Mine()

mine.list.append("World") //Array changed ["Hello", "World"]

Using a reference type:

class Mine {
    var list: NSArray = ["Hello"] {
        didSet {
            print("Array changed \(list)")
        }
    }
}

var mine = Mine()
mine.list.adding("World")
 //Doesn't print nothing
mine.list = ["World"]
//print World

I think you can do this using delegation. Create a CustomizationDataDelegate protocol:

protocol CustomizationDataDelegate {
    func choosenOptionDidChange(to newValue: PickerOption)
}

Then create a delegate property in the CustomizationData class, for instance:

internal var delegate : CustomizationDataDelegate?

And add a didSet to choosenOption:

var choosenOption : PickerOption? {
    didSet{
           if let _ = choosenOption {
              delegate?.choosenOptionDidChange(to choosenOption!)
         }
    }
}

Then register the ItemCustomizationCollectionViewCell to the CustomizationDataDelegate protocol, and then when you have some customization data, make sure the delegate is set to the cell's value:

class ItemCustomizationCollectionViewCell: UITableViewCell, CustomizationDataDelegate {

    var customizationData: CustomizationData? {
        didSet {

            if let _ = customizationData {
                if let _ = customizationData!.choosenOption {
                    // You need this in case the choosenOption has already been set
                    choosenOptionDidChange(to: customizationData!.choosenOption)
                }

                // You need this to listen for future changes
                customizationData!.delegate = self
            }
        }
    }

    let priceLabel: UILabel = {
    // ...

    // In your class' function declarations...

    //# MARK:- CustomizationDataDelegate methods 

    func choosenOptionDidChange(to newValue: PickerOption) -> Void {
        // Update the label's value here based on newValue
    }
}

Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM