Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 键值编码获取列表中的元素_Ios_Objective C_Key Value Coding - Fatal编程技术网

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

Ios 键值编码获取列表中的元素,ios,objective-c,key-value-coding,Ios,Objective C,Key Value Coding,我有两个目标: @interface AObject : NSObject @property NSArray *bObjects; @end 在aobjects的实例上使用键值编码,我可以得到bObjects的列表(@“self.bObjects”),以及bObjects名称的列表(@“self.bObjects.name”) 但是,我只需要第一个对象的名称。我的直觉是键值编码应该支持列表订阅,比如:@“boobjects[0].name” 但这似乎并不存在。如何获得单个实体;使用键值

我有两个目标:

@interface AObject : NSObject

@property NSArray *bObjects;

@end

aobjects
的实例上使用键值编码,我可以得到
bObjects
的列表(
@“self.bObjects”
),以及
bObjects
名称的列表(
@“self.bObjects.name”

但是,我只需要第一个
对象的名称。我的直觉是键值编码应该支持列表订阅,比如:
@“boobjects[0].name”

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


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

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

a对象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
@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
b对象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
@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


因此,事实证明,我有幸能够简单地重写根类(
AObject
)中的
-valueForKey:
)。它需要重复
-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];
}
-(id)valueForKey:(NSString*)字符串
{
if([string characterAtIndex:[string length]-1]==']')//正在尝试下标
{
NSRegularExpression*subscriptRegex=[[NSRegularExpression alloc]initWithPattern:@“([a-zA-Z]+)\\[[0-9]+)\]”
选项:(NSRegularExpressionOptions)0
错误:无];
NSString*key=[subscriptRegex stringbyreplacingmatcheinstall:string
选项:(NSMatchingOptions)0
范围:NSMakeRange(0,[字符串长度])
带模板:@“$1”];
id valueForKey=[self-valueForKey:key];
如果(!key | |!valueForKey | |![valueForKey响应选择器:@selector(objectAtIndexedSubscript:)]))
返回零;
NSInteger index=[[subscriptRegex stringbyreplacingmatchesisnstring:string
选项:(NSMatchingOptions)0
范围:NSMakeRange(0,[字符串长度])
withTemplate:@“$2”]integerValue];
如果((索引<0)| |(索引>=[valueForKey count]))
返回零;
返回[valueForKey对象索引下标:索引];
}
返回[super-valueForKey:string];
}

你没有。KVC不支持访问集合中的单个元素。如果你想得到这种支持,你应该打开雷达。@RobNapier,你能作弊并用
firstObject
作为钥匙吗?我不确定你能不能。如果我们假设这是可能的,那么在尝试访问给定索引处的非激励对象时,您将遇到问题(NSOutOfBoundsException)。@Wain:我刚刚尝试过这个。问题是数组上的
valueForKey:
会立即将键应用于所有数组元素。因此
[aObject valueForKeyPath:@“bObjects.firstObject.name”
尝试将
firstObject
应用于
bObjects
数组中的所有元素,而不是数组本身。-我从未找到避免这种情况的方法。对于这种特殊情况,我能想到的唯一解决方案是在
AObject
类中添加属性“firstBObject”。这是可行的,但不是很通用。