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”。这是可行的,但不是很通用。