2011-12-13 144 views
0

有没有办法找出Cocoa中的任意对象是否是基础对象?我在谈论的NSString,NSArray的,NSDictionary的等如何检查对象是否是Cocoa中的Foundation对象?

让我解释多一点...

Foundation对象(据我所知)有一些共同的特点:它们都实现了NSCoding协议,它们都可以进入PList等

因此,例如,如果我想存档一个对象图到磁盘,这将是有用的,以确保我添加到对象图的任何对象是基础对象或我的自定义对象我已经实施了NSCoding,并且这看起来很愚蠢:

if ([myObject isKindOfClass:[NSString class]] || 
    [myObject isKindOfClass:[NSNumber class]] || 
    [myObject isKindOfClass:[NSArray class]] || 
    [myObject isKindOfClass:[NSDictionary class]] || 
    [myObject isKindOfClass:[NSSet class]] || 
    ...) { 
    //add myObject to object graph 
} 

这是一个简单但可能没用的例子,我遇到的问题是我编写的一些代码将字典转换为使用格式字符串与%@说明符的url params字符串,但我不希望任意对象在那里去,因为我不想在我的网址参数的内存地址:

//convert dictionary into url params string 
[postDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 
    if ([key isKindOfClass:[NSString class]] && ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]])) { 
     [tempPost appendFormat:@"%@=%@&", key, obj]; 
    } 
    else { 
     *stop = TRUE; 
    } 
}]; 
NSString *post; 
if ([tempPost length] > 0) { 
    post = [tempPost substringToIndex:[tempPost length] - 1]; 
} 
+2

你是什么意思? _Every_'NSString'既是Foundation也是Core Foundation('CFStringRef')对象。他们是一样的。例如,这就是为什么你在调试器中看到'NSCFString'作为字符串的基本类型的原因。 –

+0

请参阅我的编辑 – lms

回答

1

Foundation对象(据我所知)有一些共同的特点:它们都实现了NSCoding协议,他们都可以进入一个的plist等

这些都不是真实的。只有一些类符合NSCoding,并非所有类都在Foundation中,只有少数类是属性列表类。

您肯定可以使用Apple的一个归档器从对象中生成一个plist,但该对象必须符合NSCoding--请参阅上文。

因此,例如,如果我想将对象图存档到磁盘,确保我添加到对象图中的任何对象都是Foundation对象或我已实现的自定义对象NSCoding on ...

您可以使用[someObject conformsToProtocol:@protocol(NSCoding)]测试对象是否符合NSCoding

如果您需要测试某个对象是否属性列表对象,那么您必须通过测试类成员资格来做到这一点,就像您在问题中显示的那样。这样的测试将包括Core Foundation属性列表对象,并且这是正确的:CF属性列表对象在属性列表中与其基础对象一样有效,主要是因为CF和Cocoa属性列表对象可以互换(由于免费电桥)。

有效的房产列表类的完整列表在Property List Programming GuideProperty List Programming Topics for Core Foundation。当然,类名是不同的(CFString与NSString),但是由于免费桥接,它们是可以互换的。

对于所有意图和目的,NSString CFString,反之亦然,并且每隔一对免费桥接类也是如此。 想到“NSStrings vs. CFStrings”是没有用的;相反,请记住它们是相同的东西,并对待它们。

我遇到的问题是我已经写了一些代码将字典转换为使用格式化字符串与%@说明符的url params字符串,但我不想任意对象去那里,因为我不想在我的url参数中的内存地址...

这是一个类成员资格测试的有效案例。

//convert dictionary into url params string 
    if ([key isKindOfClass:[NSString class]] && ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]])) { 
     [tempPost appendFormat:@"%@=%@&", key, obj]; 
    } 

你会发现一个&你的URL这种方式结束。我之前描述过a specification for an object that formats URL query strings。您可以在您的对象实现中包含您的类成员测试。

+0

感谢您的详细解答!我有一个问题,NSString,NSNumber,NSDate,NSData,NSArray,NSSet,NSDictionary(及其可变对象)的集体名称是什么?也许我在说“基础对象”时使用了错误的术语。此外,条件子字符串负责处理@& – lms

+0

@lms:我调用所有那些减NSSet属性列表类。 (NSSet不是属性列表类) –

+1

“属性列表类型”(由CFPropertyListIsValid()检查) –

1

根据你想要做的事情 - 如果你正在编写某种诊断,并且只想排除核心类,你可以尝试获取类的名字并查看前几个字母。

if ([someObj.class.description hasPrefix:@"NS"]) { 
    NSLog(@"Well, it's an NSSomething object..."); 
} 
+0

这不会将'NSCFString'(等)标记为CF对象,这很好地证明了尝试将每个对象分类到CF容器或NS容器中的愚蠢行为。 –

1

你可以随时要求它的课程。
但你不应该立足您对代码做一些逻辑判断a path to the dark side, that is...
但严重的是,苹果露出NSString作为cluster class这意味着引擎盖下它的很多不同类别,并且可以返回到它们中的任何一个你没有保证,将来他们会一样,命名可能会改变,等等。
即使我怀疑像NSString这样的旧类会让它的底层结构发生变化,我也不会规定这种可能性并对其进行下注。