问题描述
我有一个具有以下结构的NSDocument:
@interface MyDocument : NSDocument
{
NSMutableArray *myArray;
IBOutlet NSArrayController *myArrayController;
IBOutlet MyView *myView;
}
@end
我在MyDocument.xib中实例化了NSArrayController和MyView,并已建立到文件所有者(MyDocument)的连接,因此,我很确定从Interface Builder的角度来看,我已经正确地完成了所有操作. /p>
MyView的界面很简单:
@interface MyView : NSView {
NSMutableArray *myViewArray;
}
@end
现在,在MyDocument windowControllerDidLoadNib
中,我有以下代码:
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
[myArrayController setContent:myArray];
// (This is another way to do it) [myArrayController bind:@"contentArray" toObject:self withKeyPath:@"myArray" options:nil];
[myView bind:@"myViewArray" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];
}
在调试器中,我已验证myViewArray
是NSControllerArrayProxy,因此看来我的程序绑定是正确的.但是,当我尝试将MyView方法中的对象添加到MyView myViewArray
时,它们似乎没有更新MyDocument的myArray
.我尝试了以下两种方法:
[myViewArray addObject:value];
[self addMyViewArraysObject:value];
(第二种方法如预期的那样会导致编译器错误,但是我认为,由于我对KVO的有限理解,Objective-C运行时将实现"该方法.)
我尝试更新myViewArray
的方式有问题吗?我的程序绑定有问题吗? (我正在尝试以编程方式执行此操作,因为MyView是自定义视图,并且我不想为其创建IB调色板.)
问题是您正在直接更改数组.实现编制索引访问器方法并调用它们.
KVO会覆盖您的访问器方法(只要您符合某些格式)并发布必要的通知.直接与数组对话时,您不会得到此信息.除非明确告知,否则绑定到该属性的所有内容都不知道您已经更改了该属性.当您使用访问器方法时,KVO会为您告诉其他对象.
唯一不使用访问器方法(合成或其他方法)的时间是在init
和dealloc
中,因为您将与半init
ed或-dealloc
ked对象对话.
一旦您使用自己的访问器方法对数组进行了更改,从而获得了免费的KVO通知,事情就应该起作用了:
- 该视图在更改其属性时将自动通知数组控制器,该控制器将更改其
content
属性,该属性会通知您的控制器. - 您的控制器在更改其属性时,将自动通知数组控制器,该控制器将更改其
arrangedObjects
属性,该属性会通知视图.
I have an NSDocument which has the following structure:
@interface MyDocument : NSDocument
{
NSMutableArray *myArray;
IBOutlet NSArrayController *myArrayController;
IBOutlet MyView *myView;
}
@end
I instantiate the NSArrayController and the MyView in MyDocument.xib, and have made the connections to the File's Owner (MyDocument), so I am pretty sure that from the point of view of Interface Builder, I have done everything correctly.
The interface for MyView is simple:
@interface MyView : NSView {
NSMutableArray *myViewArray;
}
@end
Now, in MyDocument windowControllerDidLoadNib
, I have the following code:
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
[myArrayController setContent:myArray];
// (This is another way to do it) [myArrayController bind:@"contentArray" toObject:self withKeyPath:@"myArray" options:nil];
[myView bind:@"myViewArray" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];
}
In the debugger, I have verified that myViewArray
is an NSControllerArrayProxy, so it would appear that my programmatic binding is correct. However, when I try to add objects in MyView's methods to the MyView myViewArray
, they do not appear to update the MyDocument's myArray
. I have tried both of the following approaches:
[myViewArray addObject:value];
[self addMyViewArraysObject:value];
(The second approach causes a compiler error, as expected, but I thought that the Objective-C runtime would "implement" this method per my limited understanding of KVO.)
Is there something wrong with how I'm trying to update myViewArray
? Is there something wrong with my programmatic binding? (I am trying to do this programmatically, because MyView is a custom view and I don't want to create an IB palette for it.)
The problem is that you're mutating your array directly. Implement indexed accessor methods and call those.
KVO overrides your accessor methods (as long as you conform to certain formats) and posts the necessary notifications. You don't get this when you talk directly to your array; anything bound to the property won't know that you've changed the property unless you explicitly tell it. When you use your accessor methods, KVO tells the other objects for you.
The only time to not use your accessor methods (synthesized or otherwise) is in init
and dealloc
, since you would be talking to a half-init
ed or -dealloc
ked object.
Once you're using your own accessor methods to mutate the array, and thereby getting the free KVO notifications, things should just work:
- The view, when mutating its property, will automatically notify the array controller, which mutates its
content
property, which notifies your controller. - Your controller, when mutating its property, will automatically notify the array controller, which mutates its
arrangedObjects
property, which notifies the view.
这篇关于如何将对象添加到以编程方式绑定的NSMutableArray?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!