在 NSArrayController 中排序

Sort in NSArrayController

我怎样才能真正将 NSMutableArray 与 NSArrayController 同步?

我的 UI 中有 class 对话框和 NSArrayController,它们将内容数组绑定到 Dialog.messages。当我直接在 Dialog.messages 中添加任何新项目时,它们在 NSArrayController 中也可用,一切看起来都不错:

[Dialog addMessage: someMsgItem];

但我还需要对消息进行排序,它仅适用于 Dialog.messages 而不适用于 NSArrayController:

 NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey: @"timestamp" ascending: YES];
 _messages = [NSMutableArray arrayWithArray: [_messages sortedArrayUsingDescriptors: @[sort]]];

如何使这些更改也适用于我的 NSArrayController?这是对话框 class 实现的一部分:

@implementation Dialog
@synthesize messages = _messages; // NSMutableArray

- (void) addMessage:(Message *)msg {
    [self insertObject:msg inMessagesAtIndex:[_messages count]];
}

- (void) removeMessage:(Message *)msg {
    [self removeObjectFromMessagesAtIndex:[self.messages indexOfObject:msg]];
}

- (NSArray *) messages {
    return [_messages copy];
}

- (void) setMessages:(NSArray *)messages {
    [self willChangeValueForKey:@"messages"];
    _messages = [NSMutableArray arrayWithArray:messages];
    [self didChangeValueForKey:@"messages"];
}

- (void) insertObject:(Message *)msg inMessagesAtIndex:(NSUInteger)index {
    [_messages insertObject:msg atIndex:index];
}

- (void) removeObjectFromMessagesAtIndex:(NSUInteger)index {
    [_messages removeObjectAtIndex:index];
}
@end

您不需要对 _messages 数组进行排序。在数组控制器上设置 sortDescriptors,它的 arrangedObjects 将根据这些描述符进行排序。然后,无论 UI(table 视图?)绑定到阵列控制器的 arrangedObjects 都会自动选择排序顺序。

复杂的是,当您需要查找与 UI 元素对应的模型对象时(例如 table 视图中的行),您需要索引到数组控制器的 arrangedObjects,不是 _messages.

如果真的要排序_messages:

  1. 不要像您显示的代码那样替换它。 Mutable 数组可以就地排序,如 [someMutableArray sortUsingDescriptors:@[sort]].

  2. 您必须确保在更改 _messages 时发出 KVO 更改通知,而不是通过调用符合 KVO 的访问器方法之一。有两种方法可以做到这一点:

    一个。调用 -willChangeValueForKey:-didChangeValueForKey:。例如:

     [self willChangeValueForKey:@"messages"];
     [_messages sortUsingDescriptors:@[sort]];
     [self didChangeValueForKey:@"messages"];
    

    我不推荐这个选项。它很容易出错,并且肯定会生成效率最低的更改通知。

    b。对来自 -mutableArrayValueForKey: 的 mutable-array-like 代理进行操作 return。例如:

    [[self mutableArrayValueForKey:@"messages"] sortUsingDescriptors:@[sort]];
    

    至少有机会生成更有效的更改通知(NSKeyValueChangeKindKeyNSKeyValueChangeReplacement)。

顺便说一句,您 不需要 在您的 -setMessages: 方法中调用 -willChangeValueForKey:-didChangeValueForKey:,事实上,你不应该。由于该方法符合 属性 的 setter 的正常命名约定,称为 "messages",KVO 自动挂钩它并生成适当的更改通知。 (如果您不希望它这样做,则必须将该键的 +automaticallyNotifiesObserversForKey: 覆盖为 return false。)