2009-09-29 7 views

답변

183

기본적으로 performSelector를 사용하면 지정된 개체에서 선택기를 호출 할 선택기를 동적으로 결정할 수 있습니다. 즉, 선택기는 런타임 전에 결정될 필요가 없습니다.

따라서 이들은 동일하더라도 :

[anObject aMethod]; 
[anObject performSelector:@selector(aMethod)]; 

두 번째 형태는이 작업을 수행 할 수 있습니다 :

SEL aSelector = findTheAppropriateSelectorForTheCurrentSituation(); 
[anObject performSelector: aSelector]; 

메시지를 보내기 전에.

+3

그것은 당신이 실제로 aSelector에 findTheAppropriateSelectorForTheCurrentSituation()의 결과를 할당하는 것이라고 지적 가치 ... 어떻게 든이 덮여 희망, 다음 [: aSelector anObject를 performSelector]를 호출합니다. @selector는 SEL을 생성합니다. –

+4

'performSelector :'를 사용하는 것은 클래스에 target-action을 구현할 때만 가능할 것입니다. 형제'performSelectorInBackground : withObject :'와'performSelectorOnMainThread : withObject : waitUntilDone :'은 종종 더 유용합니다. 백그라운드 스레드를 스폰하고, 백그라운드 스레드에서 메인 스레드로 결과를 콜백하기 위해. – PeyloW

+1

'performSelector'는 컴파일 경고를 억제하는 데 유용합니다. ('respondsToSelector'를 사용한 후처럼) 메소드가 존재한다는 것을 알게되면, Xcode가 "your_selector'에 응답하지 않을 것"이라는 말을 멈 춥니 다. 경고의 진정한 원인을 알아내는 대신에 _ 사용하지 마십시오.;) – Marc

11

@ennuikiller가 자리하고 있습니다. 기본적으로, 동적으로 생성 된 선택기는 코드를 컴파일 할 때 호출 할 메서드의 이름을 알지 못하거나 (일반적으로 그렇게 할 수 없을 때) 유용합니다.

하나의 주요한 차이점은 -performSelector:과 친구들 (multi-threaded and delayed variants 포함)은 0-2 매개 변수가있는 메서드와 함께 사용하도록 설계되어 있기 때문에 다소 제한적이라는 것입니다. 예를 들어, 매개 변수가 6 개이고 NSString을 반환하는 -outlineView:toolTipForCell:rect:tableColumn:item:mouseLocation:을 호출하는 것은 다루기가 어렵고 제공된 메소드에서 지원되지 않습니다.

+4

이렇게하려면'NSInvocation' 개체를 사용해야합니다. –

+6

또 다른 차이점은'performSelector :'와 친구들이 모두 객체 인자를 취한다는 것인데, 왜냐하면 그것의 인자가 float이기 때문에 친구들이 (예를 들어)'setAlphaValue :'를 호출 할 수 없다는 것을 의미합니다. – Chuck

+0

둘 다 훌륭한 점입니다. –

3

선택기는 다른 언어의 함수 포인터와 비슷합니다. 런타임에 호출 할 메소드를 컴파일 할 때 모를 때이를 사용합니다. 또한 함수 포인터와 마찬가지로 호출의 동사 부분 만 캡슐화합니다. 메서드에 매개 변수가 있으면 매개 변수도 전달해야합니다.

NSInvocation은 더 많은 정보를 함께 묶는 것을 제외하고는 유사한 목적을 수행합니다. 동사 부분을 포함 할뿐만 아니라 대상 개체와 매개 변수도 포함합니다. 이것은 특정 매개 변수를 사용하여 특정 객체에 대한 메소드를 지금은 아니지만 미래에 호출하려는 경우에 유용합니다. 적절한 NSInvocation을 작성하고 나중에 발사 할 수 있습니다.

+5

셀렉터는 실제로 함수 포인터와 같지 않습니다. 함수 포인터는 인수로 호출 할 수있는 것이고 선택기는이를 구현하는 모든 객체에서 특정 메소드를 호출하는 데 사용할 수 있습니다. 선택자는 함수 포인터처럼 호출의 전체 컨텍스트를 갖지 않습니다. – bbum

+1

선택기는 함수 포인터와 같지 않지만 여전히 유사하다고 생각합니다. 그들은 동사를 나타냅니다. C 함수 포인터도 동사를 나타냅니다. 추가적인 문맥없이 유용하지 않다. 선택자는 객체와 매개 변수가 필요합니다. 함수 포인터에는 매개 변수 (조작 할 오브젝트를 포함 할 수 있음)가 필요합니다. 필자가 요점은 모든 필요한 컨텍스트를 포함하는 NSInvocation 개체와 어떻게 다른지 강조하는 것이 었습니다. 아마 나의 비교는 혼란 스러웠다. 나는 사과한다. –

+1

선택자는 함수 포인터가 아닙니다. 근처에도 안. 그것들은 실제로 "C 언어"와는 반대로 메소드의 "이름"을 포함하는 단순한 C 문자열입니다. 매개 변수의 유형을 포함시키지 않기 때문에 메소드 서명도 아닙니다. 오브젝트는 같은 셀렉터에 대해 하나 이상의 메소드를 가질 수 있습니다 (다른 매개 변수 유형 또는 다른 리턴 유형). –

-6

둘 사이에는 다른 미묘한 차이가 있습니다. 여기

[object doSomething]; // is executed right away 

    [object performSelector:@selector(doSomething)]; // gets executed at the next runloop 

애플의 문서에서 발췌 한 것입니다

는 "performSelector : withObject는 : afterDelay는 :. 다음 실행 루프 사이클 동안 및 선택적 지연 기간 후 현재의 thread에 지정된 선택을 수행 그것 때문에 다음 실행 루프 사이클이 선택기를 수행 할 때까지 기다리는 동안이 메서드는 현재 실행중인 코드에서 자동 미니 지연을 제공합니다. 대기중인 순서대로 여러 큐된 선택기가 차례대로 수행됩니다. " 질문이 매우 기본적인 예를 들어

+1

귀하의 대답은 사실과 다릅니다. 인용 한 문서는'performSelector : withObject : afterDelay :'에 관한 것이지만 질문과 스 니펫은 ['performSelector :'] (http://developer.apple.com/library/mac/documentation/Cocoa/Reference/)를 사용하고 있습니다. Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html # // apple_ref/doc/uid/20000052-BBCBGHFG)와는 완전히 다른 방법입니다. 그것의 문서에서 : 'performSelector :'메소드는'aSelector' 메시지를 수신기에 직접 보내는 것과 같습니다.

+2

Josh의 설명에 감사드립니다. 당신이 올바른지; 나는 performSelector/performSelector : withObject/performSelector : withObject : afterDelay' 모두 실수였던 것과 같은 방식으로 동작한다고 생각했습니다. – avi

+0

안녕하세요. 이 답변을 삭제할 수있는 기회가 있으십니까? 당신은 충격적이라고 동의하는 것 같습니다;) – robinCTS

10

, 무슨 일이 일어날에 차이가없는

[object doSomething]; 
[object performSelector:@selector(doSomething)]; 

. doSomething은 객체에 의해 동기식으로 실행됩니다. "doSomething"만이 매우 간단한 메소드이며 아무 것도 반환하지 않으며 매개 변수가 필요하지 않습니다.

그것을했다 뭔가 같은, 좀 더 복잡 :

(void)doSomethingWithMyAge:(NSUInteger)age; 

일이 복잡하기 때문 [객체 doSomethingWithMyAge : 42];

은 더 이상 "performSelector"의 변형으로 호출 할 수 없습니다. 매개 변수가있는 모든 변형은 객체 매개 변수만을 허용하기 때문입니다. 단순히 컴파일되지 않습니다

[object performSelector:@selector(doSomethingWithMyAge:) withObject:42]; 

을 시도 :

여기에서 선택은 "doSomethingWithMyAge"일 것이다. 42 대신 NSNumber : @ (42)를 전달하면 메서드에서 기본 C 유형 (객체가 아님)을 예상하기 때문에 어느 쪽도 도움이되지 않습니다.

또한 performSelector 변종에는 최대 2 개의 매개 변수가 있습니다. 메소드에는 여러 번 더 많은 매개 변수가 있습니다.

- (id)performSelector:(SEL)aSelector; 
- (id)performSelector:(SEL)aSelector withObject:(id)object; 
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2; 

항상 객체를 반환, 내가 너무 간단한 BOOL 또는 NSUInteger을 반환 할 수 있었고, 그것은 일 :

나는 performSelector의 동기 변종이 있지만 것을 발견했다.

performSelector의 두 가지 주요 용도 중 하나는 이전 대답에서 설명한 것처럼 실행하려는 메서드의 이름을 동적으로 작성하는 것입니다. 예를 들어,

다른 용도는 나중에 현재 실행 루프에서 실행될 메시지를 비동기 적으로 개체에 전달하는 것입니다. 이를 위해 몇 가지 다른 performSelector 변형이 있습니다.

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes; 
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay; 
- (void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes; 
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; 
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; 
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; 
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait; 
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; 

는 변종 각각은 자신의 특별한 행동을 가지고

하지만, 일반적인 모든 주 뭔가 (적어도 waitUntilDone (예 나는 NSThread, NSRunLoop 및 NSObject의 같은 여러 재단 클래스 범주에서 그들을 수집) NO로 설정 됨). "performSelector"호출은 즉시 반환되며 객체에 대한 메시지는 일정 시간 후에 현재 runloop에만 적용됩니다.

지연 실행 때문에 선택기의 메서드에서 반환 값을 사용할 수 없으므로 모든 비동기 변형에서 - (void) 반환 값이 반환됩니다.

내가