在可可中使用绑定时未反映在视图中的更改

Posted

技术标签:

【中文标题】在可可中使用绑定时未反映在视图中的更改【英文标题】:Changes not reflected across view when using binding in cocoa 【发布时间】:2012-07-26 10:00:01 【问题描述】:

我正在创建一些示例应用程序来了解可可中的视图导航、绑定等概念。 这是场景: 我有一个在 MainMenu.Xib 中有一个选项卡视图(2 个选项卡)的窗口。 我在第一个选项卡中有一个文本字段,在第二个选项卡中有一个标签。我希望它们都反映相同的值,并且我想使用绑定来做到这一点。另外,我不想将提供给我的视图与选项卡视图一起使用。

这些是我已经完成的步骤。

每个选项卡视图项的视图在applicationDidFinishLaunching:方法中单独设置,使用如下代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification

// Insert code here to initialize your application

    //initialize view controllers 
    view1=[[ViewTab1 alloc] initWithNibName:@"ViewTab1" bundle:nil];
    view2=[[ViewTab2 alloc] initWithNibName:@"ViewTab2" bundle:nil];


   //set views
    [[[myTabView tabViewItems] objectAtIndex:0]setView:view1.view];
    [[[myTabView tabViewItems] objectAtIndex:1]setView:view2.view];    



myTabView 是 AppDelegate 中 MainMenu.xib 中选项卡视图的出口引用。 ViewTab1 是第一个视图控制器(和 xib)的名称。 ViewTab2 是第二个视图控制器(和 xib)的名称。

ViewTab1 有一个单一的文本字段(和一个关联的标签)。我已将此绑定到 AppDelegate 中声明的变量(名称)。 ViewTab2 有一个标签。我也将它绑定到 AppDelegate 中的同一个变量。

变量“name”在 AppDelegate 的 init 方法中被初始化。

AppDelegate.h

....
NSString *name;
....
@property(strong) ViewTab1 *view1;
@property(strong) ViewTab2 *view2;
@property (assign) IBOutlet NSTabView *myTabView;

@property (strong) NSString *name;
....

AppDelegate.m

....
@synthesize myTabView;
@synthesize view1,view2;
@synthesize name;
....
- (id)init 
self = [super init];
if (self) 
    name=@"dummy";

return self;
....

除此之外,我没有在我的程序中进行任何编码。

在 ViewTab1.xib 中,我得到一个对象并将其设为 AppDelegate 的实例,然后将 Application 对象(NSApplication)的委托引用连接到同一个对象。 (我希望这是获取 AppDelegate 对象的正确方法。)

我在 ViewTab2.xib 中做了同样的事情

然后我将 ViewTab1 中的文本字段和 ViewTab2 中的标签绑定到 AppDelegate 中的这个变量。

当我运行程序时,文本字段和标签都显示“虚拟”。但是当我更改文本字段中的值时,它不会反映在第二个选项卡(即 ViewTab2)的标签中。

请告诉我我做错了什么。

【问题讨论】:

您在 Interface Builder 中进行绑定,对吧?只是仔细检查。 【参考方案1】:

如何从任何已加载的 Nib 建立到同一个 App 委托对象的绑定?

是的,我知道所描述的这种令人沮丧的情况......经过数周和数百页的 KVO - 通知 - 绑定文档之后,我认为有一个非常简单的解决方案。

正如我们在一些信息源中发现的那样,nib 加载过程会产生新的成员实例......我们需要使用绑定连接到旧实例。

请注意,在 InterfaceBuilder 中进行的绑定会在加载 nib 后自动重定向到这些新实例

为什么不将 App delegate 的指针重定向到旧实例?

在加载 nib 的方法中,您可以在加载 nib 之前和之后测试哪个对象是应用程序委托。 如果新的与前一个不同,您可以根据需要重定向它。

这个简单的例子适用于我在 10.5.8 下的 Xcode3,目标是 OSX10.5 / i386:

// ***** SOMEWHERE IN DEFAULT APP-DELEGATE.m IMPLEMENTATION

- (IBAction) createOtherWindowFromNib: (id)sender

    // ensure that app delegate is set as you want...
    [NSApp setDelegate:self];
    NSLog(@"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE BEFORE NIB LOAD: %@ ", [[NSApp delegate] description]);


    // we can bind members of the nib to this controller over proxy object named "File’s Owner"
    NSWindowController *otherWinCapo = [[NSWindowController alloc] initWithWindowNibName: @"OtherTestWindow"];

    NSLog(@"APP-DELEGAT **** CREATE-TEST-WINDOW ***** WHO IS APP-DELEGATE AFTER NIB LOAD: %@ ", [[NSApp delegate] description]);

    // make some test for delegates before/after here if you need ...
    // usually your bindings made inside "OtherTestWindow.xib" by IB doesn’t works in this moment

    // ... and some redirection if needed
    [NSApp setDelegate:self];

    // afer that the bind made in IB inside "OtherTestWindow.xib" 
    // referred to (proxy object) "Application.delegate.myBOOL" (Bind to:Application, Model Key Path:delegate.myBOOL)
    // react to changes of myBOOL placed in default app delegate object as expected 
    // simultaneously in every open instance of "OtherTestWindow.xib"

    [otherWinCapo showWindow: otherWinCapo.window]; // we need populate the window instance on screen to see it

【讨论】:

【参考方案2】:

我认为问题在于您设置为应用程序委托类的 xib 中的对象创建了应用程序委托的 2 个不同实例,因此更改文本字段的值会更改一个实例中的名称值,但不会更改另一个。那就是你做错了,很遗憾,我现在想不出解决办法。

【讨论】:

是的。当我打印出 AppDelegate 对象时。它显示不同的ID。我这样做是希望由于只有一个 NSApplication 实例,所以只有一个 AppDelegate 对象。我仍然不明白怎么会有多个 AppDelegate 对象。还是一次只有一个 AppDelegate 对象,每当加载相应的视图时,都会使用一个新的并丢弃旧的?【参考方案3】:

您是否在NSTextField 控件中打开了“持续更新值”?

见this example。

【讨论】:

是的。我已经检查了“不断更新值”。当我在第二个视图控制器中取出 appdelegate 对象并尝试打印出“名称”的值时。它仍然显示“虚拟”

以上是关于在可可中使用绑定时未反映在视图中的更改的主要内容,如果未能解决你的问题,请参考以下文章

可可绑定错误

可可objective-c:更改自定义视图的背景颜色

可可绑定:更改时获取旧值

单击表行时可可绑定“选择”不会改变

ObservableCollection刷新视图MVVM

即使在使用view.setNeedsDisplay()刷新视图后,.isHidden属性也不会反映视图的更改