2009-09-20 238 views
4

以下代碼實現將方法轉發給NSNumber實例的NSProxy子類。-forwardInvocation與Clang-LLVM一起使用,但不與GCC一起使用

但是,當調用[nsproxy floatValue]時,我在GCC 4.2下得到0.0。

在LLVM-Clang下,我得到了正確答案42.0。

任何想法是怎麼回事?

(順便說一下,這是在垃圾回收運行)

-(id) init; 
{ 
    _result = [NSNumber numberWithFloat:42.0]; 
    return self; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 
{ 
    return [[_result class] instanceMethodSignatureForSelector:aSelector]; 
} 

- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    [anInvocation setTarget:_result]; 
    [anInvocation invoke]; 
    return; 
} 

回答

6

你的代理類不適合-floatValue宣佈消息簽名。由於它返回一個浮點數,這可能是一個問題。由於您沒有在任何地方聲明它,並且可能不會將代理對象轉換爲代表類,因此編譯器必須猜測方法簽名。在這種情況下,GCC編譯器會猜測該消息將返回一個id指針。

在Objective-C中,根據消息的簽名和機器的體系結構,可以使用不同的函數處理消息及其返回值。在x86機器上,返回浮點值的消息通過objc_msgSend_fpret調用,而返回voidid的函數使用objc_msgSend

由於GCC編譯器假定返回值是id它使用後者函數並錯誤地處理結果。 Clang能夠正確處理這個問題很有意思,但我會毫不猶豫地依靠這種行爲。最好在你的代理上聲明你將要轉發的任何方法的類別。這也有利於消除爲調用floatValue方法的代碼行生成的警告。

@interface Foo (ProxyMethods) 
- (float)floatValue; 
@end 
+0

感謝您的解釋清楚的答案,我覺得這是與期待一個id指針返回作爲浮動浮標。剛剛沒有看到任何有關潛在缺陷的Apple文檔。 – rebo 2009-09-21 08:36:24

-1

任何init方法應該調用[super init];,以防止意外行爲。因爲如此:

- (id)init { 
    self = [super init]; 
    if (self) { 
     // Your init code 
    } 
    return self; 
} 
+0

NSProxy沒有init方法。 – Barjavel 2012-11-30 19:54:12

相關問題