2015-04-29 79 views
0

我在Sprite Kit/iOS 7.0中創建自己的Button類時遇到了一些問題。當我試着回撥法「objc_msgSend」我收到以下錯誤:Objective-C:爲什麼使用參數調用objc_msgSend時會出現EXC_BAD_ACCESS異常?

Thread 1: EXC_BAD_ACCESS (code=1, address=0x8) 

這裏是我的Button類,其中的「標識符」返還給調用者:

// Header File *.h 
@property (nonatomic, readwrite, strong) NSString* identifier; 
@property (nonatomic, readonly, weak) id targetTouchUpInside; 
@property (nonatomic, readonly) SEL actionTouchUpInside; 

// Implementation File *.m 
// ... this code is in the initializer method 
NSMutableString *identifier = [[NSMutableString alloc]init]; 
[identifier appendFormat:@"%d:%d", menuId, itemId]; 
[self setIdentifier:[identifier copy]]; 

// ... this code is called to inform the observer about an event 
objc_msgSend(_targetTouchUpInside, _actionTouchUpInside, _identifier); 

這是一旦檢測到觸摸,由Button調用的回調方法。這是引發EXC_BAD_ACCESS異常的地方。 「標識符」是「零」,但只有在iPad Air上,它足夠有趣地適用於iPhone 4S。

// ... this is the callback method in the object that instantiates the button object 
- (void)itemTouchInside:(NSString*)identifier { 
    NSLog(@"ID CALLED: %@", identifier); 
} 

我觀察到,它也可以在iPad上時,我稱之爲「objc_msgSend」 ......

  • 沒有「_identifier」參數和/或
  • 與「INT」,而不是「NSString *」作爲參數
  • 帶有預定義的不可變NSString *標識符= @「fixed-string」;

但我需要動態定義_identifier,如上面的代碼片段所示。

任何想法,爲什麼這項工作在iPhone上,而不是在iPad上?

+4

爲什麼使用'objc_msgSend'而不是'performSelector:withObject:'? – rmaddy

+0

我覺得在選擇器的問題。被調用的選擇器不會懷疑只有一個NSString *作爲參數。嘗試使用'NSInvocation'而不是objc_msgSend。 –

+0

不要使用'objc_msgSend',但是如果你真的想要將它轉換爲帶有明確類型參數的非vargs形式。 '((void(*)(id,SEL,NSString *))objc_msgSend)(_ targetTouchUpInside,_actionTouchUpInside,_identifier);' – dan

回答

2

我建議你用下面的替換使用的objc_msgSend

[self.targetTouchUpInside performSelector:self.actionTouchUpInside withObject:self.identifier]; 

注意使用性質的了。你有屬性,使用它們。

正如別人提到的那樣,最好使用copy而不是strong來定義identifier屬性。消除一些可能的(和難以發現的)錯誤。

+1

有人在乎解釋倒票嗎?答案解決了OP的問題。 – rmaddy

1

爲觸摸事件創建一個協議,並且您可以進行類型檢查。你所有的問題都會消失。或者使用塊。現在有可能目標和選擇器指向錯誤種類的對象。

+0

感謝您的建議。我會介紹一個協議:-) – salocinx

相關問題