辛格尔顿的NSMutableArray由NSArrayController的多个NIB的访问(Sin

2019-09-29 17:03发布

预警 - 代码示例有点长...

我有一个单身的NSMutableArray可以从任何地方我的应用程序中进行访问。 我希望能够引用NSMutableArray从多个NIB文件,但结合到通过UI元素NSArrayController对象。 创建初期是没有问题的。 我可以引用单NSMutableArray当笔尖被加载和一切显示正常。

然而,改变NSMutableArray通过添加或删除对象不会踢掉志愿更新NSArrayController实例。 我认识到,“更改控制器的背后”被认为是可可土地不走的一部分,但我没有看到的编程方式更新任何其他方式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实例。 我们会打电话给他们myArrayControllerInNibOnemyArrayControllerInNib2 。 在每个阵列控制器init所述NIB控制器的设定数组的内容:

// In NIB one init
[myArrayControllerInNibOne setContent: [[MyGlobals sharedMyGlobals].globalArray];

// In NIB two init
[myArrayControllerInNibTwo setContent: [[MyGlobals sharedMyGlobals].globalArray];

当每个NIB初始化NSArrayController正确结合,以共享的阵列,我可以看到在UI数组内容如你所愿。 我有一个单独的后台线程,更新时,基于外部事件内容发生变化的全球阵列。 当对象需要在此背景线程以复加,我只是将它们添加到数组如下:

[[[MyGlobals sharedMyGlobals].globalArray] addObject:theNewObject];

这就是事情土崩瓦解。 我不能叫一个willChangeValueForKeydidChangeValueForKey全球阵列上,因为共享的实例没有一个键值(要我在单身类中增加这个?)

我火了一个NSNotification和捕捉,在NIB控制器,要么做一个[myArrayControllerInNibOne rearrangeObjects] ; 或将内容设置为nil并重新分配内容数组-但是这两个似乎是黑客和。 此外,设置NSArrayControllernil ,然后返回到全局阵列使UI内的视觉闪光灯作为内容被清除并重新填充。

我知道我可以直接添加到NSArrayController和数组被更新,但我没有看到一)等如何NSArrayController情况下,将更新和b)我不想明确地配合我的后台线程类的实例NIB (我也不应该有)。

我认为,正确的做法是要么莫名其妙断火的志愿通知周围的addObject在后台线程,或添加什么东西正在被存储在全局阵列中的对象。 但我不知所措。

作为一个值得注意的问题,我不使用核心数据。

任何帮助或援助将是非常赞赏。

Answer 1:

预警 - 回答有点长...

使用这种模式你的域对象。 你没有必要单身或全局变量,你需要一个普通类的普通实例。 什么是对象存储您在全局阵列? 创建一个代表模型的那部分的类。

如果你使用一个NSMutableArray作为存储它应该是内部类和对象外不可见。 例如,如果你模拟动物园,不做

[[[MyGlobals sharedMyGlobals].globalArray] addObject:tomTheZebra];

渡渡鸟

[doc addAnimal:tomTheZebra];

不要试图去观察一个可变的阵列 - 你要观察你的对象的一对多的特性。 例如。 代替

[[[MyGlobals sharedMyGlobals].globalArray] addObserver:_controller]

你要

[doc addObserver:_controller forKeyPath:@"animals" options:0 context:nil];

其中DOC是符合志愿为一对多财产“anaimals”。

为了使文档兼容志愿你需要实现这些方法(注 - 你并不需要所有的这些有些是可选的,但获得更好的性能)

- (NSArray *)animals;
- (NSUInteger)countOfAnimals;
- (id)objectInAnimalsAtIndex:(NSUInteger)i; 
- (id)AnimalsAtIndexes:(NSIndexSet *)ix;
- (void)insertObject:(id)val inAnimalsAtIndex:(NSUInteger)i;
- (void)insertAnimals:atIndexes:(NSIndexSet *)ix;
- (void)removeObjectFromAnimalsAtIndex:(NSUInteger)i;
- (void)removeAnimalsAtIndexes:(NSIndexSet *)ix;
- (void)replaceObjectInAnimalsAtIndex:(NSUInteger)i withObject:(id)val;
- (void)replaceAnimalsAtIndexes:(NSIndexSet *)ix withAnimals:(NSArray *)vals;

好吧,看起来非常可怕,但它不是那么糟糕,就像我说你不需要他们。 看到这里 。 这些方法不需要是界面的一部分,你的模型,你可以只添加: -

- (void)addAnimal:(id)val;
- (void)removeAnimal:(id)val;

写他们在KVC存取方面。 关键的一点是它不是,当它改变时发送通知的数组,数组只是幕后的存储,它是你的模型类,发送对象已被添加或删除的通知。

您可能需要调整您的应用程序。 您可能需要约NSArrayController的完全忘了。

Aaaaaannnnnyyywaaayyy ......这一切都让你什么,如果你这样做

[[[MyGlobals sharedMyGlobals].globalArray] addObject:theNewObject];

或该[doc addAnimal:tomTheZebra];

从后台线程。 你不能做到这一点。 NSMutableArray的不是线程安全的。 如果它似乎再工作会发生最好的是,志愿/绑定通知是在后台交付以及,这意味着你将尝试更新您的背景,这是你绝对不能做的GUI。 使静态数组以任何方式恐怕并不能帮助-你必须拿出相关战略..最简单的方法是performSelectorOnMainThread但除此之外,完全是另外一个问题。 线程是困难的。

而关于静态数组 - 只是停止使用静态的,你不需要它。 不是因为你有2粒,2个窗口或任何东西。 你代表你的模型和一个指针传递给你viewControllers,windowControllers,任何一个实例。 由于没有单身/静态变量与测试极大地帮助,当然,你应该做的。



文章来源: Singleton NSMutableArray accessed by NSArrayController in multiple NIB's