Objective-C: вызов селекторов с несколькими аргументами

StackOverflow https://stackoverflow.com/questions/1018195

  •  06-07-2019
  •  | 
  •  

Вопрос

В MyClass.m я определил

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

и соответствующее объявление в MyClass.h. Позже я хочу позвонить

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

в MyClass.m, но я получаю сообщение об ошибке, похожее на * Завершение работы приложения из-за невыполненной исключительной ситуации NSInvalidArgumentException, причина: '* - [MyClass myTest: withAtring:]: нераспознанный селектор, отправленный экземпляру 0xe421f0'

Я попробовал более простой случай с селектором, который не принимал аргументов, который выводил строку на консоль, и это работало просто отлично. Что не так с кодом и как я могу это исправить? Спасибо.

Это было полезно?

Решение

Подпись вашего метода:

- (void) myTest:(NSString *)

withAString является параметром (имя вводит в заблуждение, похоже, оно является частью подписи селектора).

Если вы вызываете функцию таким образом:

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

Это будет работать.

Но, как предложили другие авторы, вы можете переименовать метод:

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

И позвоните:

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

Другие советы

В Objective-C подпись селектора состоит из:

<Ол>
  • Название метода (в данном случае это будет myTest) (обязательно)
  • A ':' (двоеточие) после имени метода, если метод имеет вход.
  • Имя и ':' для каждого дополнительного ввода.
  • Селекторы не знают:

    <Ол>
  • Типы ввода
  • Тип возвращаемого значения метода.
  • Вот реализация класса, где метод executeMethodsViaSelectors выполняет другие методы класса с помощью селекторов:

    @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:);
    

    @Shane Arney

    performSelector:withObject:withObject:
    

    Вы также можете упомянуть, что этот метод предназначен только для передачи максимум 2 аргументов, и его нельзя отложить. (например, executeSelector: withObject: afterDelay:) .

    странно, что apple поддерживает только 2 объекта для отправки и не делает его более общим.

    У вашего кода две проблемы. Один был идентифицирован и ответил, а другой нет. Во-первых, в вашем селекторе отсутствовало имя его параметра. Однако даже если вы исправите это, строка все равно вызовет исключение, если ваша пересмотренная сигнатура метода по-прежнему содержит более одного аргумента. Допустим, ваш исправленный метод объявлен как

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

    Создание селекторов для методов, которые принимают несколько аргументов, вполне допустимо (например, @selector (myTestWithString: сравнениеTo :)). Однако метод executeSelector позволяет передать только одно значение myTest, который, к сожалению, имеет более одного параметра. Он выдаст ошибку и сообщит, что вы не указали достаточно значений.

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

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

    Однако есть более элегантное решение (не требующее рефакторинга). Ответ заключается в использовании NSInvocation вместе с его методами setArgument: atIndex: и invoke .

    Я написал статья, включая пример кода , если вы хотите получить более подробную информацию. Основное внимание уделяется многопоточности, но основы все еще применяются.

    Удачи!

    Ваша подпись метода не имеет смысла, вы уверены, что это не опечатка? Мне не ясно, как он компилируется, хотя, возможно, вы получаете предупреждения, которые игнорируете?

    Сколько параметров вы ожидаете от этого метода?

    Думаю, что класс должен быть определен как:

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

    У вас есть только один параметр, поэтому у вас должен быть только один:

    Возможно, вы захотите использовать% @ в вашем NSLog - это просто хорошая привычка - потом выписать любой объект - не только строки.

      

    Пользователи iOS также ожидают автокапитализацию: в стандартном текстовом поле   первая буква предложения в регистрозависимом языке   автоматически пишется с заглавной буквы.

         

    Вы можете решить, следует ли реализовывать такие функции; здесь нет   выделенный API для любой из перечисленных функций, поэтому предоставление их   это конкурентное преимущество.

    В документе Apple говорится, что для этой функции и некоторых других ожидаемых функций в настраиваемой клавиатуре нет API. поэтому вам нужно найти собственную логику для реализации этого.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top