Прослушивать обновления в массиве модели данных при изменении одного из его свойств
У меня есть обычай 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
}
}
Надеюсь, это поможет.