本文介绍了如何将对象添加到以编程方式绑定的NSMutableArray?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有以下结构的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会为您告诉其他对象.

唯一不使用访问器方法(合成或其他方法)的时间是在initdealloc中,因为您将与半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-inited or -deallocked 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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 12:01