2012-11-14 87 views
1

當我嘗試測試在較新版本的OS中引入的符號時,我遇到了一個奇怪的問題。我按照Apple guidelines使用弱鏈接符號,即在iOS中測試弱鏈接符號不能正常工作

檢查外部(EXTERN)的可用性不變或 通知名稱通過明確地比較其地址,而不是 符號裸露的名稱爲NULL或零。

重現此問題,我使用默認編譯器(Apple LLVM編譯器4.1)在最新的Xcode 4.5.2上使用最新的iOS 6 SDK。我弱化了社交框架(僅適用於iOS 6+)。和我運行在iOS 5.1這個代碼(部署目標是低於6):

NSLog(@"%p", &SLServiceTypeFacebook); 
if (&SLServiceTypeFacebook) 
    NSLog(@"Yes1"); 
if (&SLServiceTypeFacebook != NULL) 
    NSLog(@"Yes2"); 

的輸出是:

0x0 
Yes1 
Yes2 

換句話說,我們可以在運行時驗證該表達&SLServiceTypeFacebook求值到0的值。然而,對此表達式進行測試的if語句將它看作是真實的。


更新:this question,我發現這個變通辦法,沒有優化,但與優化:

typeof(&SLServiceTypeFacebook) foo = &SLServiceTypeFacebook; 
if (foo) 
    NSLog(@"Yes3"); // does not get executed on -O0, but does on any optimization 

更新: 它似乎這個問題沒有n不存在UIKit符號。運行在iOS 4.3以下幾點:

NSLog(@"%p", &UIKeyboardDidChangeFrameNotification); 
if (&SLServiceTypeFacebook) 
    NSLog(@"Yes1"); 
if (&SLServiceTypeFacebook != NULL) 
    NSLog(@"Yes2"); 

輸出是:

0x0 

我假設的區別是,UIKit的符號具有NS_AVAILABLE_IOS()宏旁邊,這樣莫名其妙的編譯器能夠正確地處理它。在社交框架符號的情況下,它沒有NS_AVAILABLE_IOS()宏,因爲整個社交框架本身僅在iOS 6以後纔可用(即該框架的版本之後可用的符號,所以我猜不需要這個宏?);但是然後編譯器不能正確處理該符號。

+0

不應第一行是'的NSLog(@ 「%P」,SLServiceTypeFacebook)''那裏是SLServiceTypeFacebook'一個指針? –

+0

@RoboticCat:不,不可用的弱鏈接符號的地址是0,嘗試訪問該符號將導致段錯誤。 – user102008

+0

好的 - 最後的想法(然後我出來的想法) - NSLog(@「%x」,&SLServiceTypeFacebook)呢? –

回答

0

你確定你不想檢查SLRequest類是否存在而不是檢查這個常量嗎?

在任何情況下,問題是編譯器正在優化測試(它將此解釋爲測試在編譯時爲真的常量表達式)。您可以通過將此地址讀入本地易變的變量來規避此情況。或者你可以在運行時動態搜索符號。

但我會考慮只是檢查SLRequest類。

這裏有至少這三個選項:

#include <dlfcn.h> 

NSString* const * volatile check = &SLServiceTypeFacebook; 
if (check != NULL) 
    NSLog(@"SLServiceTypeFacebook is defined"); 

// Another approach would be to call dlsym() at runtime 
// to search for this symbol: 
if (dlsym(RTLD_DEFAULT, "SLServiceTypeFacebook")) 
    NSLog(@"SLServiceTypeFacebook found via dlsym"); 

// But if you really just wanted to know is if SLRequest 
// is available, you should really just do this: 
if ([SLRequest class]) 
    NSLog(@"SLRequest class is available"); 

所有的這些都應該按照您是在iOS5.1與iOS6的期待。

希望有所幫助。

+0

1)我還沒有打開任何優化,2)這是測試符號可用性的可接受方式,並且用於工作(請參閱http://stackoverflow.com/questions/3002833/weak-linking-on -iphone-refuse-to-work) – user102008

+0

在Xcode中,您可以檢查編譯器輸出以驗證是否正在編譯此條件,即使在調試配置文件中也是如此。如果你覺得這是一個叮噹聲的bug,那麼radr當然就是這樣的場所。否則,這裏是與運輸代碼一起使用的選項。我認爲,對班級本身的測試仍然更好。 –

+0

@FirozeLafeer你確定這是一個有意的優化,還是隻是一個猜測?我對此感到莫名其妙,因爲在修正之前,在編譯時如何知道這個值呢?我試圖弄清楚這是(或者是)一個錯誤還是其他的事情,如果它仍然是一個值得關注的問題?還有一個很好的分析,以確切地顯示發生了什麼? – jhabbott

-2

只是NSClassFromString檢查,如果你能得到的類.. objC是所有類反正:d

+0

1)Objective-C不是全部類。 2)我在這裏檢查變量的可用性,而不是類,所以這是完全不相關的。 3)你甚至不需要使用'NSClassFromString'來檢查類的可用性。簡單地檢查'[TheClass class]',或者直接傳遞任何其他消息到'[TheClass someMessage]'就可以正常工作。如果類不可用,類對象將爲'nil'。 – user102008

+0

即時通訊充分意識到它不是所有的類。 :P因此是 - >:D |但是一個好的交易集中在類和檢查某個類或方法時檢查符號可能是不必要的。 –

+0

另一個答案也建議檢查類btw! > | –

相關問題