Когда использовать двоеточие с помощью @selector

Просто приступим к разработке iPhone и Objective-C.

Вчера я пытался добавить Observer для уведомления в моем представлении, и я продолжал получать эту ошибку:

unrecognized selector sent to instance

Я отследил это до того факта, что мне нужно было добавить конечную двоеточие в аргумент селектора:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nameOfMySelector:) name:@"BBLocationServicesAreDisabled" object:nil];

Сегодня я подумал, что умен, потому что когда я настраивал аргумент действия для кнопки, я вспомнил вчерашнюю ошибку и добавил двоеточие к аргументу действия. Аргумент действия принимает @selector, точно так же, как аргумент селектора при настройке наблюдателя для NSNotification, поэтому я решил, что NSNotification правильно.

Тем не менее, с помощью следующего кода:

[self.callToActionButton addTarget:self action:@selector(nameOfMySelector:) forControlEvents:UIControlEventTouchUpInside];

Я получаю точно такую же ошибку:

unrecognized selector sent to instance

Что дает? Почему один @selector требует @selector двоеточия, а другой нет? Каковы правила, которым я должен следовать, когда это должно быть включено и когда это должно быть прекращено, и почему я не могу всегда делать одно или другое?

Спасибо!

Ответ 1

Как упоминалось boltClock, характер, на который вы ссылаетесь, на самом деле является двоеточием. Разница между @selector(method) и @selector(method:) является сигнатурой метода. Второй вариант ожидает передачи параметра.

@selector(method) ожидал бы метод: -(void)method

@selector(method:) ожидал бы метод: -(void)method:(id)someParameter

Ответ 2

Кажется, у вас отсутствует одна концепция: двоеточие, в некотором роде, является частью имени метода. Например, метод

-(IBAction) doIt:(id)sender;

имеет имя doIt:. Таким образом, двоеточие должно использоваться для ссылки на этот метод.
Но этот метод не имеет двоеточия в конце

-(IBAction) doItWithoutParameter;

То же самое касается методов, принимающих несколько аргументов, у них есть имена типа doItWithParam1:andParam2:

Ответ 3

Селектор представляет имя метода, а количество двоеточий в селекторе соответствует количеству аргументов в соответствующем методе:

  • mySelector - нет двоеточия, нет аргументов, например. - (void)mySelector;, [self mySelector];
  • mySelectorWithFoo: - один двоеточие, один аргумент, например. - (void)mySelectorWithFoo:(Foo *)foo;, [self mySelectorWithFoo:someFoo];
  • mySelectorWithFoo:withBar: - два двоеточия, два аргумента, например. - (void)mySelectorWithFoo:(Foo *)foo bar:(Bar *)bar;, [self mySelectorWithFoo:someFoo bar:someBar];

и т.д.

Также возможно иметь селектор без "именования параметров". Его не рекомендуется, так как он не сразу определяет, какие параметры:

  • mySelector:: - два двоеточия, два аргумента, например. - (void)mySelector:(Foo *)foo :(Bar *)bar;, [self mySelector:someFoo :someBar];
  • mySelector::: - три двоеточия, три аргумента, например. - (void)mySelector:(int)x :(int)y :(int)z;, [self mySelector:2 :3 :5];

Ответ 4

Двоеточие указывает, что метод принимает параметр.

[someObject performSelector:@selector(doSomething:)] означает, что doSomething ожидает параметр.

[someObject performSelector:@selector(doSomething)] означает, что doSomething не нуждается в каких-либо параметрах.

Ответ 5

В вашем случае:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(nameOfMySelector:) name:@"BBLocationServicesAreDisabled" object:nil];

- (void) nameOfMySelector: (NSNotification *) notification {
    /* this method would require the semi-colon */
}

или в этом случае:

[self.callToActionButton addTarget:self action:@selector(nameOfMySelector:) forControlEvents:UIControlEventTouchUpInside];

- (void) nameOfMySelector: (id) sender {
    /* this method would also require the semi-colon */
}