在 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
:
不要像您显示的代码那样替换它。 Mutable 数组可以就地排序,如 [someMutableArray sortUsingDescriptors:@[sort]]
.
您必须确保在更改 _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]];
至少有机会生成更有效的更改通知(NSKeyValueChangeKindKey
为 NSKeyValueChangeReplacement
)。
顺便说一句,您 不需要 在您的 -setMessages:
方法中调用 -willChangeValueForKey:
和 -didChangeValueForKey:
,事实上,你不应该。由于该方法符合 属性 的 setter 的正常命名约定,称为 "messages",KVO 自动挂钩它并生成适当的更改通知。 (如果您不希望它这样做,则必须将该键的 +automaticallyNotifiesObserversForKey:
覆盖为 return false。)
我怎样才能真正将 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
:
不要像您显示的代码那样替换它。 Mutable 数组可以就地排序,如
[someMutableArray sortUsingDescriptors:@[sort]]
.您必须确保在更改
_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]];
至少有机会生成更有效的更改通知(
NSKeyValueChangeKindKey
为NSKeyValueChangeReplacement
)。
顺便说一句,您 不需要 在您的 -setMessages:
方法中调用 -willChangeValueForKey:
和 -didChangeValueForKey:
,事实上,你不应该。由于该方法符合 属性 的 setter 的正常命名约定,称为 "messages",KVO 自动挂钩它并生成适当的更改通知。 (如果您不希望它这样做,则必须将该键的 +automaticallyNotifiesObserversForKey:
覆盖为 return false。)