简体   繁体   English

键值编码获取列表中的元素

[英]Key-Value Coding Get Element in List

I have two objects: 我有两个对象:

@interface AObject : NSObject

@property NSArray *bObjects;

@end

@interface BObject : NSObject

@property NSString *name;

@end

Using key-value coding on an instance of AObject , I can get the list of bObjects ( @"self.bObjects" ), and a list of bObjects ' names ( @"self.bObjects.name" ). AObject的实例上使用键值编码,我可以获得bObjects的列表( @"self.bObjects" )和bObjects名称的列表( @"self.bObjects.name" )。

However, what I want is the name of only the first of bObjects . 但是,我想要的只是第一个bObjects的名称。 My gut is that key-value coding should support list subscripting, like this: @"bObjects[0].name" . 我的直觉是键值编码应支持列表下标,例如: @"bObjects[0].name"

But that doesn't seem to exist. 但这似乎并不存在。 How do I get a single entity; 我如何获得一个实体? the name of an AObject 's first BObject , using key-value coding? 使用键值编码的AObject的第一个BObject的名称?

Footnote: I realized in my last question I was stupidly conflating NSPredicate and KV-coding. 脚注:我意识到在最后一个问题中,我愚蠢地将NSPredicate和KV编码混为一谈。

As Martin R mentioned in the comments, currently the best option would be to create a firstBObject property in the AObject class. 正如Martin R在评论中提到的那样,当前最好的选择是在AObject类中创建firstBObject属性。

AObject.h/m AObject.h /米

@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 BObject.h /米

@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

Usage: 用法:

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"]);

Results 结果

(
A1B1, A1B1,
A2B1, A2B1,
A3B1 A3B1
)

So as it turns out, I had the fortune of being able to simply override -valueForKey: in the root class ( AObject ). 事实证明,我很幸运能够简单地在根类( AObject )中重写-valueForKey: AObject It bears repeating that -valueForKeyPath: calls -valueForKey: on every key, which is cool. 值得重申的是-valueForKeyPath:呼吁-valueForKey:在每一个关键,这是很酷。

Since that might not be applicable to everyone, and this might be too much manipulation of default, expected behavior, this definitely not the "right" answer. 由于这可能并不适用于所有人,并且可能过多地操纵了默认的预期行为,所以这绝对不是 “正确”的答案。

But here it is anyway: 但是无论如何,这里是:

- (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];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM