gpt4 book ai didi

objective-c - 是否可以在 KVC 中使用通配符?

转载 作者:太空狗 更新时间:2023-10-30 04:01:12 27 4
gpt4 key购买 nike

我正在尝试像这样在 KVC 中使用通配符。

这可能吗?

或者有没有其他方法可以使用通配符来表示成员变量?

@interface MyClass : NSObject
@property(nonatomic, retain) NSNumber *test1;
@property(nonatomic, retain) NSNumber *test2;
@end

@implementation MyClass{
NSNumber * test1;
NSNumber * test2;
}
@synthesize test1;
@synthesize test2;
@end

使用通配符

MyClass *testClass = [[[MyClass alloc] init] autorelease];
testClass.test1 = @50;

NSLog(@"test value : %@", [testClass valueForKey:@"*1"]);

详细代码。

我想要的一个真正原因是通过整数或 nsnumber 类型的值来指示实例的成员变量。如果可能,设置值和读取任何实例的值会更容易。

例如属性部分复制。

MyClass *testClass = [[[MyClass alloc] init] autorelease];
testClass.year_1 = @2012;
testClass.quarter_2 = @3;
testClass.month_3 = @8;
testClass.day_4 = @20;
testClass.week_5 = @4;

// copy propertys to other instance.
// Normal way
MyClass *testClassCopy = [[[MyClass alloc] init] autorelease];
testClassCopy.year_1 = testClass.year_1;
testClassCopy.quarter_2 = testClass.quarter_2;
testClassCopy.month_3 = testClass.month_3;
testClassCopy.day_4 = testClass.day_4;

// copy propertys by using wildcard
for (int j = 0; j < 4; j++) {
NSString *indicate = [NSString stringWithFormat:@"*%@", [NSNumber numberWithInteger:j + 1]];
NSNumber *sourceProperty = [testClass valueForKey:indicate];
[testClassCopy setValue:sourceProperty forKey:indicate];
}

最佳答案

我将通过添加正则表达式和使用类别来提高你的通配符:

要了解正则表达式如何处理它,请阅读 NSRegularExpression Class Reference .

特点:

  • 使用正则表达式匹配各种键
  • 使用适用于任何实例的类别
  • 缓存每个类的键列表
  • 完整的 KVC 支持(不仅是属性,还有访问器方法和 iVar!)
  • 与当前的 KVC 方法完美集成(仅在未找到 key 时才使用正则表达式,从而提高性能)
  • 子类化不会把事情搞砸,就像@JamesWebster 的解决方案
  • 不会用 NSObject 的方法不必要地污染键列表
  • 返回匹配键和值的 NSDictionary

缺点:

  • 使用正则表达式,速度较慢且理解起来更复杂
  • 类的初始查找速度较慢(必须遍历所有方法和 iVar)
  • 自动覆盖 -valueForUndefinedKey: 方法,因此这可能会破坏一些现有代码(将其移至自己的方法进行修复)。
  • 目前不支持设置值(按照设计,这完全是另一回事)。
  • 结果中可能有重复的 keyPaths(这不是最大的问题,但源于 KVC 匹配很复杂,我必须执行所有规则)
  • 使用 NSRegularExpression,它仅适用于 iOS 4 及更高版本(不是最大的问题)。

版本历史:

  • 1.0:初始版本

所以,这是代码:

NSObject+KVCRegex.h:

//
// NSObject+KVCRegex.h
// TestProj
//
// Created by Richard Ross on 8/20/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSObject (KVCRegex)

// custom implemenation
-(id) valueForUndefinedKey:(NSString *)key;

@end

NSObject+KVCRegex.m:

//
// NSObject+KVCRegex.m
// TestProj
//
// Created by Richard Ross on 8/20/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//

#import "NSObject+KVCRegex.h"
#import <objc/runtime.h>

@implementation NSObject (KVCRegex)

static NSSet *keyPathsForClass(Class cls)
{
NSMutableSet *keys = [NSMutableSet set];

do
{
if (cls == [NSObject class])
{
// nothing good can come from trying to use KVC on NSObject methods
break;
}

unsigned count = 0;
Method *methods = class_copyMethodList(cls, &count);

for (int i = 0; i < count; i++) {
// make sure that the method returns a value
const char *methodName = sel_getName(method_getName(methods[i]));

char returnType[64];
method_getReturnType(methods[i], returnType, 64);
if (strcmp(returnType, "v") == 0)
continue;

// make sure that the method takes no args (except for self & _cmd)
if (method_getNumberOfArguments(methods[i]) == 2)
{
// add a duplicate entry for ones matching 'is'
if (strstr(methodName, "is") == methodName)
{
char *newStr = strdup(methodName + 2);
newStr[0] = tolower(newStr[0]);

[keys addObject:[NSString stringWithUTF8String:newStr]];

free(newStr);
}

[keys addObject:[NSString stringWithUTF8String:methodName]];
}
}

free(methods);

// now copy iVars

count = 0;
Ivar *ivars = class_copyIvarList(cls, &count);
for (int i = 0; i < count; i++)
{
const char *ivarName = ivar_getName(ivars[i]);

if (strstr(ivarName, "_") == ivarName)
[keys addObject:[NSString stringWithUTF8String:ivarName + 1]]; // iVar name starting with _<key>

[keys addObject:[NSString stringWithUTF8String:ivarName]];
}

free(ivars);
} while ((cls = [cls superclass]));

return [NSSet setWithSet:keys];
}

// returns a dictionary based on 'key' as a regex
-(id) valueForUndefinedKey:(NSString *)key
{
// lookup for later use
static NSMutableDictionary *keyClassPairs;
if (!keyClassPairs)
keyClassPairs = [NSMutableDictionary dictionary];

if (!keyClassPairs[[self class]])
{
keyClassPairs[(id<NSCopying>)[self class]] = keyPathsForClass([self class]);
}

NSSet *keyPaths = keyClassPairs[[self class]];

// assume 'key' is a regex
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:key options:0 error:nil];
NSMutableArray *matches = [NSMutableArray array];

for (NSString *keyPath in keyPaths)
{
NSRange matchRange = [regex rangeOfFirstMatchInString:keyPath options:0 range:(NSRange) { 0, keyPath.length }];

if (matchRange.length == keyPath.length)
{
// we have a match
[matches addObject:keyPath];
}
}

if (matches.count)
return [self dictionaryWithValuesForKeys:matches];
else
[NSException raise:NSUndefinedKeyException format:@"Could not find a key that matches the regex in %@", key];

return nil;
}

@end

示例:

@interface MyObject : NSObject
{
@public
int normalIvar;
id _underscoreIvar;
}

@property id someProp;
@property BOOL isProperty;
@property int nativeProp;

-(void) notAKey;
-(id) aKey;

@end

@implementation MyObject

@synthesize someProp, isProperty, nativeProp;

-(void) notAKey
{
NSLog(@"Not a key!");
}

-(id) aKey
{
return @"Value";
}

@end

int main()
{
@autoreleasepool {
MyObject *obj = [MyObject new];

obj.someProp = @"a property";
obj.nativeProp = 15;
obj.isProperty = YES;
obj->normalIvar = 172;
obj->_underscoreIvar = @"Ivar";

NSString *regex = @"[a|s].*"; // match a key starting with 'a' or 's', then matching anything else after

NSLog(@"%@", [obj valueForKey:regex]); // prints "{ aKey = 'Value', someProp = 'a property' }"

regex = @"_.*"; // match a key starting with '_', and then match anything else after

NSLog(@"%@", [obj valueForKey:regex]); // prints "{ _underscoreIvar = 'Ivar' }"

regex = @".*"; // match any key declared for this object

NSLog(@"%@", [obj valueForKey:regex]); // prints "{ "_underscoreIvar" = Ivar; aKey = Value; isProperty = 1; nativeProp = 15; normalIvar = 172; property = 1; someProp = "a property"; underscoreIvar = Ivar; }"

regex = @"(?i)[A-J].*"; // match (case insensitive) a key starting with A - J

NSLog(@"%@", [obj valueForKey:regex]); // prints "{ aKey = value; isProperty = 1; }"
}
}

关于objective-c - 是否可以在 KVC 中使用通配符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12040409/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com