【问题标题】:Issues using NSIndexPath as key in NSMutableDictionary?使用 NSIndexPath 作为 NSMutableDictionary 中的键的问题?
【发布时间】:2013-11-05 23:50:36
【问题描述】:

尝试使用NSIndexPath 作为keyNSMutableDictionary 中存储和检索值可能会失败,有什么特别的原因吗?

我最初尝试这样做是为了将NSMutableDictionaryUITableViewCell 高度(self.cellHeights)存储为UITableView。每次您点击UITableViewCell 时,该单元格将根据NSMutableDictionary 中存储的特定indexPath 的值在两个不同的高度之间扩展或收缩:

- (CGFloat)tableView:(UITableView *)tableView 
           heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSNumber *heightNSNumber = [self.cellHeights objectForKey:indexPath];
    if (!heightNSNumber)
    {
        heightNSNumber = [NSNumber numberWithFloat:100.0];
        [self.cellHeights setObject:heightNSNumber forKey:indexPath];
    }
    return [heightNSNumber floatValue];
}

- (void)tableView:(UITableView *)tableView  
        didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSNumber *heightNSNumber = [self.cellHeights objectForKey:indexPath];
    if (!heightNSNumber)
    {
        heightNSNumber = [NSNumber numberWithFloat:100.0];
        [self.cellHeights setObject:heightNSNumber forKey:indexPath];
    }

    if ([heightNSNumber floatValue] == 100.0)
    {
        [self.cellHeights setObject:[NSNumber numberWithFloat:50.0] 
                             forKey:indexPath];
    } else {
        [self.cellHeights setObject:[NSNumber numberWithFloat:100.0] 
                             forKey:indexPath];
    }
    [tableView beginUpdates];
    [tableView endUpdates];
}

由于我不知道的原因,通过[self.cellHeights objectForKey:indexPath] 获取tableView:didSelectRowAtIndexPath: 内的单元格高度可以正常工作。但是,尝试通过[self.cellHeights objectForKey:indexPath] 获取tableView:heightForRowAtIndexPath: 中的单元格高度总是返回 nil,因为用于存储高度的 indexPath 似乎与用于获取单元格高度的 indexPath 不匹配,即使它们具有相同的indexPath.sectionindexPath.row 的值。因此,“相同”索引路径的新对象被添加到self.cellHeights(因为self.cellHeights.count 此后增加)。

当您使用行 ([NSNumber numberWithInteger:indexPath.row]) 作为键将单元格高度存储在 NSMutableDictionary 中时,不会发生这种情况......所以这就是我现在正在做的事情,但我想了解为什么indexPath 不能作为关键。

【问题讨论】:

    标签: objective-c cocoa-touch uitableview nsmutabledictionary nsindexpath


    【解决方案1】:

    虽然我在讨论中迟到了,但这里有一个快速简单的解决方案,允许您使用 NSIndexPath 实例作为字典键。

    只需通过添加以下行重新创建 indexPath:

    indexPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
    

    瞧。 tableView:heightForRowAtIndexPath: 在内部使用 NSMutableIndexPath 实例(正如您在断点中看到的那样)。不知何故,这些实例在计算哈希键时似乎与 NSIndexPath 不合作。

    通过将其转换回NSIndexPath,一切正常。

    【讨论】:

    • 圣钼。这让我发疯。几个小时以来,我一直在梳理互联网,试图弄清楚为什么我的字典对我知道存在的 indexPath 返回 nil。绝对令人抓狂。感谢发帖。
    【解决方案2】:

    @Jean 的回答似乎可以接受,但这个问题一直是answered in more detail here。简而言之,UITableView 有时使用NSMutableIndexPath 的实例而不是NSIndexPath,这两个类的实例永远不会相等,因为[NSMutableIndexPath class] != [NSIndexPath class]。解决方法是始终为依赖于isEqualhash 的任何内容生成一个键NSIndexPath,例如查找字典键:

    - (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath
    {
        if ([indexPath class] == [NSIndexPath class]) {
            return indexPath;
        }
        return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
    }
    

    【讨论】:

      【解决方案3】:

      要使对象作为NSDictionary 的键可靠地工作,必须实现几件事,即isEqual:hashCopyable 协议。

      我不太确定 NSIndexPath 是否曾打算用作字典的键(因为它被用作数组的索引)。

      我的猜测是 hash 没有为类的不同实例正确实现。另请注意,某些表委托方法使用NSIndexPath 调用,而另一些则使用NSMutableIndexPath 调用。这可能会有所不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多