【问题标题】:How can I observe a specific element with Swift collection types using property observers?如何使用属性观察器观察具有 Swift 集合类型的特定元素?
【发布时间】:2018-03-18 18:41:56
【问题描述】:

在回答How do I know if a value of an element inside an array was changed?的问题时受到启发,答案是使用Property Observer来检查数组是否被修改。

但是,如何确定属性观察器中集合类型中的更新元素是什么?例如:

class MyClass {
    var strings: [String] = ["hello", "world", "!"] {
        didSet(modifiedStrings) {
            print("strings array has been modified!!:")
            print(modifiedStrings)
        }
    }
}

let myClass = MyClass()
myClass.strings.append("a string")
myClass.strings[0] = "Hello"
myClass.strings.removeLast()

请注意didSet 代码已为每个添加、更新或删除操作调用,但我如何才能确切知道受影响的元素是什么?有没有办法通过将strings 数组标记为 Property Observer 来实现这一点?

我在询问 Swift 中的所有集合类型,因为我认为它们应该是相同的行为,它是关于观察的。

谢谢。

【问题讨论】:

    标签: arrays swift dictionary set property-observer


    【解决方案1】:

    感谢@hnh,基于他的answer,我最终得到:

    class MyNumber: NSObject {
    
        // NOTE that it works in both "willSet" and "didSet"
    
        /// Array ///
        var arrayNumbers: [String] = ["one", "two", "three"] {
            willSet {
                let oldStrings = Set(arrayNumbers)
                let newStrings = Set(newValue)
    
                print("removed from array: \(oldStrings.subtracting(newStrings))")
                print("added to array:   \(newStrings.subtracting(oldStrings))")
    
                print("----------")
            }
        }
    
        /// Set ///
        var setNumbers: Set = ["one", "two", "three"] {
            didSet(newSet) {
                print("removed from set: \(newSet.subtracting(setNumbers))")
                print("added to set:   \(setNumbers.subtracting(newSet))")
    
                print("----------")
            }
        }
    
        var dictionaryNumbers = ["1": "one", "2": "two", "3": "three"] {
            didSet(modified) {
                let oldKeys = Set(dictionaryNumbers.keys)
                let newKeys = Set(modified.keys)
    
                let oldValues = Set(dictionaryNumbers.values)
                let newValues = Set(modified.values)
    
                print("removed from dictionary (keys): \(newKeys.subtracting(oldKeys)) (values): \(newValues.subtracting(oldValues))")
                print("added to dictionary (keys):   \(oldKeys.subtracting(newKeys)) (values):    \(oldValues.subtracting(newValues))")
                print("----------")
    
    //            print("removed (values): \(newValues.subtracting(oldValues))")
    //            print("added (values):   \(oldValues.subtracting(newValues))")
    
            }
        }
    }
    

    执行:

    let myNumber = MyNumber()
    
    /// Array ///
    
    // adding:
    myNumber.arrayNumbers.append("four")
    /* Logging:
     removed: [] means that nothing has been removed form the array
     added:   ["four"]
     ----------
     */
    
    // updating:
    myNumber.arrayNumbers[0] = "One"
    /* Logging:
     removed: ["one"]
     added:   ["One"]
     ----------
     */
    
    // deleting:
    myNumber.arrayNumbers.removeLast()
    /* Logging:
     removed: ["four"]
     added:   [] means that nothing has been added to the array
     ----------
     */
    
    
    /// Set ///
    
    // adding:
    myNumber.setNumbers.insert("four")
    /* Logging:
     removed from set: [] means that nothing has been removed form the set
     added to set:   ["four"]
     ----------
     */
    
    // deleting:
    myNumber.setNumbers.removeFirst()
    /* Logging:
     removed from set: ["three"] // sets are unsorted...
     added to set:   [] means that nothing has been added to the set
     ----------
     */
    
    
    /// Dictionary ///
    
    // adding:
    myNumber.dictionaryNumbers["4"] = "four"
    /* Logging:
     removed from dictionary (keys): [] (values): []
     added to dictionary (keys):   ["4"] (values):    ["four"]
     ----------
     */
    
    // updating:
    myNumber.dictionaryNumbers["1"] = "One"
    /* Logging:
     removed from dictionary (keys): [] (values): ["one"]
     added to dictionary (keys):   [] (values):    ["One"]
     ----------
     */
    
    // deleting:
    myNumber.dictionaryNumbers.removeValue(forKey: "2")
    /* Logging:
     removed from dictionary (keys): ["2"] (values): ["two"]
     added to dictionary (keys):   [] (values):    []
     ----------
     */
    

    这显示了如何处理数组、集合和字典。

    【讨论】:

      【解决方案2】:

      您可以在应用更改之前使用willSet 观察者计算更改。像这样:

      struct YourStruct {
        var strings : [ String ] = [ "Hello", "World", "!" ] {
          willSet {
            // in here you have `newValue` containing the new array which
            // will be set. Do any comparison operations you want, like:
            let oldStrings = Set(strings)
            let newStrings = Set(newValue)
            print("removed: \(oldStrings.substract(newStrings))")
            print("added:   \(newStrings.substract(oldStrings))")
            // (Just for demonstration purposes, if they are Sets, they
            //  should be Sets in the first place, obviously.)
          }
        }
      }
      

      【讨论】:

      • 很好的答案。您忘记了打印末尾的“)”。 + 1
      • didSet 中与oldValue 进行比较也可以。
      • 感谢您的回答。这听起来很合乎逻辑,我只是​​根据你的答案添加了一个答案,展示了如何处理数组、集合和字典。数组有一个特殊情况(因为它是唯一已排序的)我无法实现(因为您在检查减法时将其更改为 set - 这是未排序的),即知道修改后元素的索引,你知道我该怎么做吗?顺便说一句,在接受您的答案之前,我将等待检查是否会发布任何新答案:)
      猜你喜欢
      • 1970-01-01
      • 2020-12-26
      • 2020-08-15
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多