2014-06-15 5 views
4

나는 object 타겟을 가지고 있고, selector을보고, displayTitle@"displayTitle: object.selector"이라는 문자열을 출력 할 클래스를 만들고있다. 그런 다음 valueobject.selector 일 때마다 KVO를 통해 자신을 등록하므로보기 컨트롤러에보기를 업데이트하도록 알릴 수 있습니다. 나는 이것을 추상적이고 재사용 가능한 방법으로 사용하여 객체의 다양한 속성에 대한 설명을 사용자에게 보여줍니다.objc_msgSend가 EXC_BAD_ACCESS를 발생시키는 이유는 무엇입니까?

object.selector의 값을 얻으려고하면 LLVM gives errors when you use performSelector with a dynamic selector이므로 [object performSelector:selector]을 사용할 수 없습니다. 그래서 정확히 this answer을 제안했습니다. 나는 objc_msgSend(object, selector)을 사용했습니다.

- (instancetype)initWithSelector:(SEL)selector onObject:(NSObject*)object displayTitle:(NSString*)displayTitle { 
    self = [super init]; 

    if (self) { 
     id value; 

     if ([object respondsToSelector:selector) { 
      // Used objc_msgSend instead of performSelector to suppress a LLVM warning which was caused by using a dynamic selector. 
      value = objc_msgSend(object, selector); 
     } else { 
      return nil; 
     } 

     [self setItemDescription:[NSString stringWithFormat:@"%@: %@", displayTitle, value]]; 
    } 

    return self; 
} 

그리고 EXC_BAD_ACCESS! 당신은 스크린 샷에서 볼 수 있듯이

Screenshot

, 나는 이 [object selector] 일을하고 있는지 확인했다.

어떻게되고 있으며 어떻게 해결할 수 있습니까?

답변

3

당신은 너무 ARC가의 개막과 (당신이 왼쪽에있는 스택에서 볼 수 있듯이 충돌이 objc_retain에) 결과 객체를 유지하려고 유형 id의 변수에 objc_msgSend 호출의 결과를 할당합니다. 그러나 결과는 오브젝트가 아니라 값 8의 정수이며, objc_retain이 포인터가됩니다. 그러나 유효한 포인터가 없으므로 EXC_BAD_ACCESS이됩니다.

value의 유형을 NSUInteger (또는 기타 비 객체 유형)으로 변경하면됩니다. 그러나 모든 잠재 selector이 동일한 유형의 데이터를 반환하는지 확인하십시오. 또는 ARC가 보유 할 수있는 객체 (또는 nil)를 항상 반환해야합니다.

+0

:이 경우에 순서가 그것을 사용하는, 당신은 뭔가를해야 * 및 * 비 대상? @ VincentGeurci가 말했듯이이 속성을 NSNumber로 만들 수 있다는 것을 알고 있습니다. 그러나이 값을 응용 프로그램의 다른 위치에서 자주 사용해야 할 필요가 있으므로 다소 불편할 것입니다. –

+0

오브젝트 및 비 오브젝트를 보유하는 objective-c의 유일한 해결책은 오브젝트 (예 : NSNumber)를 보유하는 것입니다.최근 llvm 버전에서는'NSNumber * x = @ (5)'를 사용하여 리터럴을 찾을 수 있습니다. 더 자세한 내용을 보려면 Swift가 어느 정도 이것을 해결할 때까지 기다리십시오. –

+0

값을 introspect하여 자동으로 인코딩/디코딩 할 목적으로 C 유형을 결정할 수도 있습니다. 하지만 그게 사소한 (낮은 수준의 objc_xxx 메서드), NSNumber 방법 훨씬 쉽게. –

3

귀하의 값이 정수 8 일 수 있습니까? 아크

덕분에, 그 값은 EXC_BAD_ACCESS, 0x8이되는 보호 주소를 설명 할 수있는 0x8이 ADRESS에서 유지, 즉 유지되도록 시도된다. 그 문제의 경우

, 그냥 목표 - C에서 메소드를 호출하기 위해, 그냥 C에서 함수를 호출과 같은 NSNumber

3

로 값을 포장, 당신의 정확한 유형의 서명을 알 필요가 방법.

objc_msgSend 및 관련 함수를 사용하는 경우이를 호출하기 전에 올바른 함수 포인터 유형으로 변환해야합니다. 다른 답변과 주석에서 메서드에 매개 변수가없고 반환 유형이 NSInteger 인 것으로 나타났습니다. '값'은 객체인지, 내 클래스 개체를 처리 할 수 ​​있도록하면 그렇게 ARC 결정할 수 있도록하는 방법이 있나요

NSInteger value; 
NSInteger (*f)(id, SEL) = (NSInteger (*)(id, SEL))objc_msgSend; 
value = f(object, selector); 
+0

참조는 https://issues.apache.org/jira/browse/CB-6150이며 여기 https://developer.apple.com/library/content/documentation/General/Conceptual/CocoaTouch64BitGuide/ConverttingYourAppto64-Bit/YourAppto64로 변환 중입니다. -Bit.html – isaacselement