Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios DiffableDataSource是否能够正确处理项目移动、项目修改和项目移动&;修改?_Ios_Swift - Fatal编程技术网

Ios DiffableDataSource是否能够正确处理项目移动、项目修改和项目移动&;修改?

Ios DiffableDataSource是否能够正确处理项目移动、项目修改和项目移动&;修改?,ios,swift,Ios,Swift,我一直觉得,一个好的Diff库,应该具备检测以下3个方面的能力 当项目被移动时 当项目被修改时 移动和修改项目时 当我查看WWDC 2019的源代码时,我注意到这些实现只能够检测移动,而不能检测修改 class WiFiController { struct Network: Hashable { let name: String let identifier = UUID() func hash(into hasher: inout

我一直觉得,一个好的Diff库,应该具备检测以下3个方面的能力

  • 当项目被移动时
  • 当项目被修改时
  • 移动和修改项目时

  • 当我查看WWDC 2019的源代码时,我注意到这些实现只能够检测移动,而不能检测修改

    class WiFiController {
    
        struct Network: Hashable {
            let name: String
            let identifier = UUID()
    
            func hash(into hasher: inout Hasher) {
                hasher.combine(identifier)
            }
            static func == (lhs: Network, rhs: Network) -> Bool {
                return lhs.identifier == rhs.identifier
            }
        }
    
    移动好啊 检测到移动,因为我们检测到标识符=0从索引0移动到索引1

    修改。失败 未检测到修改,因为前后的标识符保持不变
    func==
    仅考虑标识符


    我想,我可以通过修改上面的类来解决这个问题

    class WiFiController {
    
        struct Network: Hashable {
            let name: String
            let identifier = UUID()
    
            func hash(into hasher: inout Hasher) {
                hasher.combine(name, identifier)
            }
            static func == (lhs: Network, rhs: Network) -> Bool {
                return lhs.name == rhs.name && lhs.identifier == rhs.identifier
            }
        }
    
    移动好啊 检测到移动,因为我们检测到name=“WiFi A”标识符=0从索引0移动到索引1

    修改。好的(也许) 检测到修改,因为我们检测到name=“WiFi A”标识符=0被修改为name=“WiFi X”标识符=0

    或者,图书馆可能会得出结论,我已从索引0中删除name=“WiFi A”标识符=0,并在索引0中插入新的name=“WiFi X”标识符=0

    移动和修改。失败 无法检测移动,因为我们正在比较名称和标识符


    我可以知道你如何解决上述问题吗

    我认为这可能是
    DiffableDataSource
    库的一个缺点。由于仅基于
    散列
    =
    ,它无法回答这两个问题

  • 2个旧项目和新项目是否相同
  • 如果这两个项目相同,它们的内容是否也相同
  • 当我们实现
    func==
    时,我们只能使其比较标识或比较内容,但不能两者兼而有之


    p/s

    如果我检查一下安卓系统做得如何,它们提供了两种方法

  • 比较识别

  • 比较内容

    /**
     * Called by the DiffUtil to decide whether two object represent the same Item.
     * <p>
     * For example, if your items have unique ids, this method should check their id equality.
     *
     * @param oldItemPosition The position of the item in the old list
     * @param newItemPosition The position of the item in the new list
     * @return True if the two items represent the same object or false if they are different.
     */
    public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);
    
    /**
     * Called by the DiffUtil when it wants to check whether two items have the same data.
     * DiffUtil uses this information to detect if the contents of an item has changed.
     * <p>
     * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)}
     * so that you can change its behavior depending on your UI.
     * For example, if you are using DiffUtil with a
     * {@link RecyclerView.Adapter RecyclerView.Adapter}, you should
     * return whether the items' visual representations are the same.
     * <p>
     * This method is called only if {@link #areItemsTheSame(int, int)} returns
     * {@code true} for these items.
     *
     * @param oldItemPosition The position of the item in the old list
     * @param newItemPosition The position of the item in the new list which replaces the
     *                        oldItem
     * @return True if the contents of the items are the same or false if they are different.
     */
    public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);
    
    /**
    *由DiffUtil调用以确定两个对象是否表示同一项。
    *
    *例如,如果项目具有唯一的id,则此方法应检查其id是否相等。
    *
    *@param oldItemPosition项目在旧列表中的位置
    *@param newItemPosition项目在新列表中的位置
    *@如果两个项目代表相同的对象,则返回True;如果两个项目不同,则返回false。
    */
    公共抽象布尔值是相同的(int-oldItemPosition,int-newItemPosition);
    /**
    *当DiffUtil想要检查两个项是否具有相同的数据时,调用该函数。
    *DiffUtil使用此信息检测项目的内容是否已更改。
    *
    *DiffUtil使用此方法检查相等性,而不是{@link Object#equals(Object)}
    *因此,您可以根据您的UI更改其行为。
    *例如,如果将DiffUtil与
    *{@link RecyclerView.Adapter RecyclerView.Adapter},您应该
    *返回项目的视觉表示是否相同。
    *
    *仅当{@link#areItemsTheSame(int,int)}返回时才调用此方法
    *{@code true}用于这些项目。
    *
    *@param oldItemPosition项目在旧列表中的位置
    *@param newItemPosition项目在新列表中的位置,该列表将替换
    *旧项目
    *@如果项目内容相同,则返回True;如果项目内容不同,则返回false。
    */
    公共抽象布尔值是相同的内容(int oldItemPosition,int newItemPosition);
    
  • class WiFiController {
    
        struct Network: Hashable {
            let name: String
            let identifier = UUID()
    
            func hash(into hasher: inout Hasher) {
                hasher.combine(name, identifier)
            }
            static func == (lhs: Network, rhs: Network) -> Bool {
                return lhs.name == rhs.name && lhs.identifier == rhs.identifier
            }
        }
    
    Index   Before                                      After               
    0       [name = "WiFi A", identifier = 0]           [name = "WiFi B", identifier = 1]    
    1       [name = "WiFi B", identifier = 1]           [name = "WiFi A", identifier = 0]
    2       [name = "WiFi C", identifier = 2]           [name = "WiFi C", identifier = 2]
    
    Index   Before                                      After               
    0       [name = "WiFi A", identifier = 0]           [name = "WiFi X", identifier = 0]    
    1       [name = "WiFi B", identifier = 1]           [name = "WiFi B", identifier = 1]
    2       [name = "WiFi C", identifier = 2]           [name = "WiFi C", identifier = 2]
    
    Index   Before                                      After               
    0       [name = "WiFi A", identifier = 0]           [name = "WiFi B", identifier = 1]    
    1       [name = "WiFi B", identifier = 1]           [name = "WiFi X", identifier = 0]
    2       [name = "WiFi C", identifier = 2]           [name = "WiFi C", identifier = 2]
    
    /**
     * Called by the DiffUtil to decide whether two object represent the same Item.
     * <p>
     * For example, if your items have unique ids, this method should check their id equality.
     *
     * @param oldItemPosition The position of the item in the old list
     * @param newItemPosition The position of the item in the new list
     * @return True if the two items represent the same object or false if they are different.
     */
    public abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);
    
    /**
     * Called by the DiffUtil when it wants to check whether two items have the same data.
     * DiffUtil uses this information to detect if the contents of an item has changed.
     * <p>
     * DiffUtil uses this method to check equality instead of {@link Object#equals(Object)}
     * so that you can change its behavior depending on your UI.
     * For example, if you are using DiffUtil with a
     * {@link RecyclerView.Adapter RecyclerView.Adapter}, you should
     * return whether the items' visual representations are the same.
     * <p>
     * This method is called only if {@link #areItemsTheSame(int, int)} returns
     * {@code true} for these items.
     *
     * @param oldItemPosition The position of the item in the old list
     * @param newItemPosition The position of the item in the new list which replaces the
     *                        oldItem
     * @return True if the contents of the items are the same or false if they are different.
     */
    public abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);