Прослушивать обновления в массиве модели данных при изменении одного из его свойств

У меня есть обычай UITableViewCell который имеет массив модели данных и UILabel как это:

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
}

Теперь данные CustomizationData выглядят так:

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

и PickerOption это:

class PickerOption {
    let title: String
    let price: String

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

Мой вопрос:

Я хочу послушать, как будет установлен choosenOption customizationData, и получить название, чтобы изменить UILabelтекст к выбранной цене.

Я попытался добавить didSet в customizationData, но он не вызывается, так как меняется одно из его свойств. Не сами данные настройки.

2 ответа

То, что вы можете сделать, возможно, но вызвать didSet customizationOptions Вам нужно изменить его значение, в основном, двумя способами:

  • если customizationOptions это ссылочный тип, вам нужно изменить его с другой ссылкой
  • если customizationOptions это тип значения, такой как Array, didSet должен быть вызван также, если вы измените значение внутри него, потому что массив полностью меняет структуру.

Чтобы понять лучше, вот пример.
Используя тип значения:

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

var mine = Mine()

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

Используя тип ссылки:

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

Я думаю, что вы можете сделать это с помощью делегации. Создайте протокол CustomizationDataDelegate:

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

Затем создайте свойство делегата в классе CustomizationData, например:

internal var delegate : CustomizationDataDelegate?

И добавьте didSet в choosenOption:

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

Затем зарегистрируйте ItemCustomizationCollectionViewCell в протоколе CustomizationDataDelegate, а затем, когда у вас есть некоторые данные настройки, убедитесь, что для делегата установлено значение ячейки:

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

Надеюсь, это поможет.

Другие вопросы по тегам