1

我有两个对象:

@interface AObject : NSObject

@property NSArray *bObjects;

@end

 

@interface BObject : NSObject

@property NSString *name;

@end

在 的实例上使用键值编码AObject,我可以得到bObjects( @"self.bObjects") 的列表和bObjects' 名称 ( @"self.bObjects.name") 的列表。

但是,我想要的只是第一个的名称bObjects。我的直觉是键值编码应该支持列表下标,像这样:@"bObjects[0].name".

但这似乎不存在。如何获得单个实体;AObject第一个的名称BObject,使用键值编码?

脚注:我在上一个问题中意识到我愚蠢地将 NSPredicate 和 KV 编码混为一谈。

4

2 回答 2

1

正如 Martin R 在评论中提到的,目前最好的选择是firstBObject在类中创建一个属性AObject

AObject.h/m

@class BObject;

@interface AObject : NSObject
+ (AObject*)aObjectWithBObjects:(NSArray*)bObjects;
@property NSArray *bObjects;
@property (nonatomic, readonly) BObject *firstBObject;
@end

@implementation AObject
+ (AObject*)aObjectWithBObjects:(NSArray*)bObjects
{
    AObject *ao = [[self alloc] init];
    ao.bObjects = bObjects;
    return ao;
}
- (BObject*)firstBObject
{
    return [self.bObjects count] > 0 ? [self.bObjects objectAtIndex:0] : nil;
}
@end

BObject.h/m

@interface BObject : NSObject
+ (BObject*)bObjectWithName:(NSString*)name;
@property NSString *name;
@end

@implementation BObject
+ (BObject*)bObjectWithName:(NSString *)name
{
    BObject *bo = [[self alloc] init];
    bo.name = name;
    return bo;
}
@end

用法:

NSArray *aobjects = @[
                      [AObject aObjectWithBObjects:@[
                       [BObject bObjectWithName:@"A1B1"],
                       [BObject bObjectWithName:@"A1B2"],
                       [BObject bObjectWithName:@"A1B3"],
                       [BObject bObjectWithName:@"A1B4"]
                       ]],
                      [AObject aObjectWithBObjects:@[
                       [BObject bObjectWithName:@"A2B1"],
                       [BObject bObjectWithName:@"A2B2"],
                       [BObject bObjectWithName:@"A2B3"],
                       [BObject bObjectWithName:@"A2B4"]
                       ]],
                      [AObject aObjectWithBObjects:@[
                       [BObject bObjectWithName:@"A3B1"],
                       [BObject bObjectWithName:@"A3B2"],
                       [BObject bObjectWithName:@"A3B3"],
                       [BObject bObjectWithName:@"A3B4"]
                       ]]
                      ];
NSLog(@"%@", [aobjects valueForKeyPath:@"firstBObject.name"]);

结果


A1B1,A2B1

A3B1

于 2013-08-22T19:32:23.423 回答
1

事实证明,我很幸运能够-valueForKey:在根类 ( AObject) 中简单地覆盖。它需要重复-valueForKeyPath:-valueForKey:​​用每个键,这很酷。

由于这可能不适用于所有人,而且这可能是对默认的预期行为的过多操纵,因此这绝对不是“正确”的答案。

但无论如何,这里是:

- (id)valueForKey:(NSString *)string
{
    if ([string characterAtIndex: [string length] - 1] == ']') // Trying to subscript
    {
        NSRegularExpression *subscriptRegex = [[NSRegularExpression alloc] initWithPattern: @"([a-zA-Z]+)\\[([0-9]+)\\]"
                                                                                   options: (NSRegularExpressionOptions)0
                                                                                     error: nil];

        NSString *key = [subscriptRegex stringByReplacingMatchesInString: string
                                                                 options: (NSMatchingOptions)0
                                                                   range: NSMakeRange(0, [string length])
                                                            withTemplate: @"$1"];
        id valueForKey = [self valueForKey: key];
        if (!key || !valueForKey || ![valueForKey respondsToSelector: @selector(objectAtIndexedSubscript:)])
            return nil;

        NSInteger index = [[subscriptRegex stringByReplacingMatchesInString: string
                                                                    options: (NSMatchingOptions)0
                                                                      range: NSMakeRange(0, [string length])
                                                               withTemplate: @"$2"] integerValue];
        if ((index < 0) || (index >= [valueForKey count]))
            return nil;

        return [valueForKey objectAtIndexedSubscript: index];
    }

    return [super valueForKey: string];
}
于 2013-08-23T12:12:34.920 回答