2009-06-19 3 views
135

와 선택기를 호출, 나는 목표 - C는 : MyClass.m에서 여러 인수

- (void) myTest: (NSString *) withAString{ 
    NSLog(@"hi, %@", withAString); 
} 

과에서 MyClass.h에서 해당 선언을 정의했다. 나중에 내가 MyClass.m에서

[self performSelector:@selector(mytest:withAString:) withObject: mystring]; 

전화 싶지만 때문에 캐치되지 않는 예외 'NSInvalidArgumentException', 이유에 응용 프로그램을 종료 *과 같은 에러가납니다 '* - [MyClass에 MYTEST : withAtring :] : 인스턴스로 보낸 인식 할 수없는 선택기 0xe421f0 '

콘솔에 문자열을 출력하고 아무 문제가없는 선택자를 사용하여 더 간단한 경우를 시도했지만 제대로 작동했습니다. 코드의 문제점과 해결 방법은 무엇입니까? 감사.

+4

귀하의 게시물은 '복수 인수'에 대해 질문하지만 귀하는 하나만 사용합니다. 이제 나는 누군가가 array/dict/whatever에 포장하는 것 이외에 어떻게 여러 인자로 그것을 할 것인지 궁금합니다. – RonLugge

답변

130

귀하의 메소드 서명은 다음과 같습니다

- (void) myTest:(NSString *) 

withAString는 (이름, 오해의 소지가 선택의 서명의 일부처럼 보이는) 매개 변수로 발생합니다. 이 방식으로 함수를 호출하는 경우

:

[self performSelector:@selector(myTest:) withObject:myString]; 

이 작동합니다.

그러나 다른 포스터는 제안으로, 당신은 방법 이름을 바꿀 수 있습니다

- (void)myTestWithAString:(NSString*)aString; 

을 그리고 전화 :

[self performSelector:@selector(myTestWithAString:) withObject:myString]; 
+1

감사! 사소한 수정. "mytest :"의 "t"는 "T"로 대문자이어야합니다. 자기 performSelector : @ 선택기 (mytest :) withObject : myString]; – Stu

+0

감사합니다. 내 게시물을 업데이트했습니다. –

+1

사람들이이 답변의 혜택을 입은 것을 보았으므로 나는 응답을 검토했습니다. 나는 그 호출이 단순히 다음과 같이 제안 할 것이다 : - (void) testWithString : (NSString *) aString; –

2

클래스는 다음과 같이 정의해야한다고 생각 :

- (void) myTestWithSomeString:(NSString *) astring{ 
    NSLog(@"hi, %s", astring); 
} 

가 하나만 있어야한다, 그래서 당신은 단지 하나의 매개 변수가 있습니다 :

당신은 또한 당신의 NSLog의 %에 @를 사용하여 고려할 수 있습니다

- 들어갈 수있는 좋은 습관 일뿐입니다. 문자열이 아닌 모든 객체를 작성합니다.

3

메서드 서명이 의미가 없으므로 오타가 아닙니까? 나는 그것이 컴파일하는 방법이 명확하지 않다. 아마 당신이 무시하고 있다는 경고를 받고있을 것인가?

얼마나 많은 매개 변수를 사용하면이 메서드를 사용할 수 있습니까?

+0

죄송합니다. 작성하고 있습니다. 필자는 그것을 타이핑하고 코드를 복사하고 붙여 넣는 대신에 더 간단하게 만들려고했지만이 과정에서 실수를 범했습니다. 이 메서드는 하나의 매개 변수를 사용합니다. 내가 인쇄하고 싶은 문자열. – Stu

297

을 목표 - C에서는 선택의 서명은 다음과 같이 구성

  1. 메소드 이름 (이 경우 'myTest') (필수)
  2. 메서드에 입력 값이있는 경우 메서드 이름 뒤에 ':'(콜론)이옵니다.
  3. 추가 입력 할 때마다 이름과 ':'가 표시됩니다.

    1. 입력 유형
    2. 방법의 반환 유형 :

    선택기에 대한 지식이 없습니다. 여기

는 performMethodsViaSelectors 방법은 선택기의 방법으로 다른 클래스의 방법을 수행하는 클래스 구현의 :

@implementation ClassForSelectors 
- (void) fooNoInputs { 
    NSLog(@"Does nothing"); 
} 
- (void) fooOneIput:(NSString*) first { 
    NSLog(@"Logs %@", first); 
} 
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second { 
    NSLog(@"Logs %@ then %@", first, second); 
} 
- (void) performMethodsViaSelectors { 
    [self performSelector:@selector(fooNoInputs)]; 
    [self performSelector:@selector(fooOneInput:) withObject:@"first"]; 
    [self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second"]; 
} 
@end 

단일 입력을 가지고 당신은 선택을 만들 것이다, 그래서 선택기를 만들 방법 그것을 위해 그렇게 :

SEL myTestSelector = @selector(myTest:); 
+3

좋은 답변입니다. 약간 명료하게하려면 선택기 이름에 최소한 하나 이상의 부분이 있어야하며 매개 변수를 사용할 수도 그렇지 않을 수도 있습니다. 그렇다면 콜론이 있어야합니다. 두 개 이상의 파트가있는 선택기 이름은 각 부분 뒤에 콜론이 있어야합니다. "-useFoo : andBar : toDoSomething"형식의 선택기를 사용하는 것은 적합하지 않습니다. 덕분에 –

+0

. 이것과 함께 고군분투하고 잠시 도움을 청했습니다! –

+0

입력 매개 변수는 정수가 어떨까요? 이 경우 어떻게해야합니까? –

7

코드에는 두 가지 문제점이 있습니다. 하나는 확인되고 대답되었지만 다른 하나는 그렇지 않았습니다. 첫 번째는 선택기에 매개 변수의 이름이 누락되었습니다. 그러나 수정 한 경우에도 여전히 수정 된 메소드 서명에 여전히 하나 이상의 인수가 포함되어 있다고 가정하면 예외가 발생합니다. 이제 수정 된 방법은 다음과 같이 선언되어 있다고 가정 해 봅시다 : 여러 인수를 메소드에 대한 선택기 만들기

-(void)myTestWithString:(NSString *)sourceString comparedTo:(NSString *)testString ; 

완벽하게 유효합니다 (예를 들어, @selector (myTestWithString : comparedTo :)). 그러나 performSelector 메서드를 사용하면 하나의 값만 myTest에 전달할 수 있습니다.이 값은 불행히도 하나 이상의 매개 변수를가집니다. 오류가 발생하여 충분한 값을 제공하지 못했음을 알립니다.

당신은 항상 유일한 매개 변수이기로 컬렉션을 가지고 당신의 방법을 다시 정의 할 수 있습니다 :

-(void)myTestWithObjects:(NSDictionary *)testObjects ; 

그러나, 더 우아한 해결책 (즉 리팩토링을 필요로하지 않습니다)이있다. 대답은 NSInvocation과 함께 setArgument:atIndex:invoke 메서드를 사용하는 것입니다.

자세한 내용은 an article, including a code example을 작성했습니다. 초점은 스레딩에 있지만 기본 사항은 계속 적용됩니다.

행운을 빈다.

13

@Shane Arney는

performSelector:withObject:withObject: 

또한이 방법은 최대 2 개 인자를 전달하는 것을 언급 할 수 있습니다, 그것은 지연 될 수 없습니다. (예 : performSelector:withObject:afterDelay:)

사과 만 보낼 수 2 개 객체를 지원하고보다 일반적인하게 didnt는 것을 좀 이상한

+2

정보 주셔서 감사합니다. 지연을받을 수 없어서 지금은 이유를 알고 있습니다. 참고로 두 개체의 한계를 극복하기 위해 배열을 전달한 다음 메서드에서 사용했습니다. – JScarry

0

iOS 사용자도 기대 autocapitalization :..의 표준 텍스트 필드에 첫 글자 대소 문자를 구분하는 언어의 문장은 가 자동으로 대문자로

이 당신은 이러한 기능을 구현할지 여부를 결정할 수 있습니다

이 ;. 그래서 가 경쟁 우위 그들에게 제공, 위에 나열된 기능 중 하나에 대한 전용 API가 없다 .

애플 문서는이 기능과 사용자 정의 키 보드의 다른 예상 기능에 사용할 수있는 API가 없다고 말하고 있습니다. 그래서 이것을 구현하기 위해 자신의 논리를 찾아야합니다.