Раннее предупреждение - пример кода немного длинный...
У меня есть одноэлементный NSMutableArray, к которому можно получить доступ из любого места в моем приложении. Я хочу иметь возможность ссылаться на NSMutableArray
из нескольких файлов NIB, но привязываться к элементам пользовательского интерфейса через объекты NSArrayController
. Первоначальное создание не проблема. Я могу сослаться на синглтон NSMutableArray
, когда загружается NIB, и все выглядит нормально.
Однако изменение NSMutableArray
путем добавления или удаления объектов не запускает KVO для обновления экземпляров NSArrayController
. Я понимаю, что «изменение за спиной контроллера» считается запретной частью Cocoa-land, но я не вижу другого способа программно обновить NSMutableArray
и позволить каждому NSArrayController
быть уведомленным (за исключением того, что это не работает курс...).
Я упростил классы ниже, чтобы объяснить.
Упрощенный заголовок одноэлементного класса:
@interface MyGlobals : NSObject {
NSMutableArray * globalArray;
}
@property (nonatomic, retain) NSMutableArray * globalArray;
Упрощенный одноэлементный метод:
static MyGlobals *sharedMyGlobals = nil;
@implementation MyGlobals
@synthesize globalArray;
+(MyGlobals*)sharedDataManager {
@synchronized(self) {
if (sharedMyGlobals == nil)
[[[self alloc] init] autorelease];
}
return sharedMyGlobals;
}
-(id) init {
if(self = [super init]) {
self.globals = [[NSMutableArray alloc] init];
}
return self
}
// ---- allocWithZone, copyWithZone etc clipped from example ----
В этом упрощенном примере заголовок и модель для объектов в массиве:
Заголовочный файл:
@interface MyModel : NSObject {
NSInteger myId;
NSString * myName;
}
@property (readwrite) NSInteger myId;
@property (readwrite, copy) NSString * myName;
-(id)initWithObjectId:(NSInteger)newId objectName:(NSString *)newName;
@end
Файл метода:
@implementation MyModel
@synthesize myId;
@synthesize myName;
-(id)init {
[super init];
myName = @"New Object Name";
myId = 0;
return self;
}
@end
Теперь представьте два файла NIB с соответствующими экземплярами NSArrayController
. Мы назовем их myArrayControllerInNibOne
и myArrayControllerInNib2
. Каждый контроллер массива в init
контроллера NIB устанавливает содержимое массива:
// In NIB one init
[myArrayControllerInNibOne setContent: [[MyGlobals sharedMyGlobals].globalArray];
// In NIB two init
[myArrayControllerInNibTwo setContent: [[MyGlobals sharedMyGlobals].globalArray];
Когда каждый NIB инициализируется, NSArrayController
правильно привязывается к общему массиву, и я могу видеть содержимое массива в пользовательском интерфейсе, как и следовало ожидать. У меня есть отдельный фоновый поток, который обновляет глобальный массив при изменении содержимого на основе внешнего события. Когда объекты нужно добавить в этот фоновый поток, я просто добавляю их в массив следующим образом:
[[[MyGlobals sharedMyGlobals].globalArray] addObject:theNewObject];
Вот где вещи разваливаются. Я не могу вызвать willChangeValueForKey
и didChangeValueForKey
в глобальном массиве, потому что общий экземпляр не имеет значения ключа (должен ли я добавлять это в класс singleton?)
Я мог запустить NSNotification
и поймать это в контроллере NIB и либо выполнить [myArrayControllerInNibOne rearrangeObjects]
; или установите для содержимого значение nil
и переназначьте содержимое массиву, но оба они выглядят как хаки и. кроме того, установка NSArrayController
в nil
, а затем обратно в глобальный массив вызывает визуальную вспышку в пользовательском интерфейсе, поскольку содержимое очищается и повторно заполняется.
Я знаю, что могу добавить непосредственно к NSArrayController
, и массив будет обновлен, но я не вижу а) как будут обновляться другие экземпляры NSArrayController
и б) я не хочу явно привязывать класс фонового потока к экземпляру NIB (и я не должен).
Я думаю, что правильный подход состоит в том, чтобы либо каким-то образом отключить уведомление KVO вокруг addObject
в фоновом потоке, либо добавить что-то к объекту, который хранится в глобальном массиве. Но я в растерянности.
Следует отметить, что я НЕ использую Core Data.
Любая помощь или помощь будут очень признательны.