2011-12-13 190 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這樣的舊類會讓它的底層結構發生變化,我也不會規定這種可能性並對其進行下注。