首页 > 解决方案 > 1:many:many 模型中的 NSArrayController 绑定细节

问题描述

我有一个简单的程序来说明我在真实程序中要做什么。我有一个一对多关系的一对多关系,如果顶层有多个选择,我无法让多个选择编辑正常工作:

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

@interface ManyMany : NSObject

@property int value1;
@property int value2;

@end

@implementation ManyMany

- (id)copyWithZone:(NSZone *)zone {
    ManyMany *m = [[ManyMany allocWithZone:zone] init];
    m.value1 = self.value1;
    m.value2 = self.value2;

    return m;
}

- (BOOL)isEqual:(ManyMany *)other {
    if (other == nil) {
        return NO;
    }

    if (self.value1 == other.value1 && self.value2 == other.value2) {
        return YES;
    }

    return NO;
}

@end

@interface Many : NSObject

@property NSArray< ManyMany * > *manyManys;

@end

@implementation Many

@end

@interface One : NSObject 

@property NSArray< Many * > *manys;

@end

@implementation One

@end

@interface MyObserver : NSObject

@property NSObject *value;

@end

@implementation MyObserver

@end

int main()
{
    One *one = [[One alloc] init];
    one.manys = @[ [[Many alloc] init], [[Many alloc] init] ];
    one.manys[0].manyManys = @[ [[ManyMany alloc] init], [[ManyMany alloc] init] ];
    one.manys[1].manyManys = @[ [[ManyMany alloc] init], [[ManyMany alloc] init] ];

    NSArrayController *manyController = [[NSArrayController alloc] init];
    manyController.objectClass = [Many class];

    NSArrayController *manyManyController = [[NSArrayController alloc] init];
    manyManyController.objectClass = [ManyMany class];

    [manyController bind:NSContentArrayBinding toObject:one withKeyPath:@"manys" options:nil];
    [manyManyController bind:NSContentArrayBinding toObject:manyController withKeyPath:@"selection.manyManys" options:nil];

    MyObserver *o = [[MyObserver alloc] init];
    [o bind:@"value" toObject:manyManyController withKeyPath:@"selection.value1" options:nil];

    [manyController setSelectionIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,2)]];
    [manyManyController setSelectionIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,2)]];

    [manyManyController setValue:@(2) forKeyPath:@"selection.value1"];

    NSLog(@"contents:");
    Many *m;
    for (m in one.manys) {
        NSLog(@"many @ %p", m);
        ManyMany *mm;
        for (mm in m.manyManys) {
            NSLog(@"manyMany @ %p", mm);
            NSLog(@" %d %d", mm.value1, mm.value2);
        }
    }
}

此输出显示第一组 2 个已正确设置,而不是全部四个。如果我将 ManyManyController 的内容绑定更改为selectedObjects.manyManys,然后设置 setValue:forKeyPath: 将正确设置所有 4,但是与观察者的绑定将崩溃。

我从根本上缺少什么?

标签: objective-ccocoa-bindings

解决方案


  1. 您缺少用于多选绑定的内容数组。

一个索引集合,指定当 contentArray 或 contentObject 绑定返回多选标记时 NSArrayController 将其视为其内容对象的项目。

[manyManyController bind:NSContentArrayForMultipleSelectionBinding toObject:manyController withKeyPath:@"selection.@unionOfArrays.manyManys" options:nil];
  1. contentArray 绑定不返回多选标记,因为Many.manyss 相等。打开alwaysUsesMultipleValuesMarker将解决此问题,但也会禁用Many.
manyController.alwaysUsesMultipleValuesMarker = YES;
  1. 选择所有 4 个 4 ManyManys。
[manyManyController setSelectionIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,4)]];

推荐阅读