Xcode опускает имена параметров блока

У меня есть свойство блока, которое выглядит так:

@property (nonatomic, copy) void (^indexChangeBlock)(NSInteger index);

Когда я пытаюсь установить значение для этого свойства, автозаполнение Xcode опускает имя параметра, оставляя мне что-то вроде этого:

[self.segmentedControl3 setIndexChangeBlock:^(NSInteger) {
    code
}];

Затем Xcode показывает ошибку Parameter name omitted. Я знаю, что могу решить эту проблему, добавив имя параметра вручную, чтобы оно выглядело так:

[self.segmentedControl3 setIndexChangeBlock:^(NSInteger index) {
    code
}];

Мои вопросы: как я могу заставить Xcode автоматически добавлять имена параметров. Или, другими словами, предотвратить их удаление.


person Hesham    schedule 21.01.2013    source источник
comment
Но тип indexChangeBlock это просто void (^)(NSInteger). В типе функции или типе блока нет имени параметра. Это бессмысленно для языка.   -  person newacct    schedule 22.01.2013
comment
Да, это бессмысленно для языка, но полезно для автозаполнения в Xcode, особенно когда ваш код будет использоваться другими.   -  person Hesham    schedule 22.01.2013
comment
FWIW, я только что протестировал приведенный выше синтаксис в Xcode 12.5.1, и автозаполнение теперь включает имя параметра.   -  person Rob    schedule 26.06.2021
comment
Рад узнать, что это было исправлено спустя 8 лет.   -  person Hesham    schedule 30.06.2021


Ответы (2)


возможное решение:

typedef void (^IndexChangeBlock)(NSInteger index);

и определите свою собственность с помощью

@property (nonatomic, copy) IndexChangeBlock indexChangeBlock;

а если добавить

- (void)setIndexChangeBlock:(IndexChangeBlock)indexChangeBlock;

все должно работать

person Jonathan Cichon    schedule 21.01.2013
comment
Xcode автоматически дополнит это до [self.segmentedControl3 setIndexChangeBlock:(IndexChangeBlock)indexChangeBlock], так что это еще больше раздражает. - person Hesham; 21.01.2013
comment
отредактировал мой ответ, к сожалению, вам нужно добавить декларацию установки вручную - person Jonathan Cichon; 21.01.2013
comment
Теперь работает как шарм, спасибо! Также стоит упомянуть, что он может работать и без typedef. Подойдет только свойство и метод установки - (void)setIndexChangeBlock:(void (^)(NSInteger index))indexChangeBlock;. - person Hesham; 22.01.2013

В обостренном расстройстве я сделал макрос, закрепляющий этот грубый процесс..

#define BlockProperty(SIGNATURE,TYPENAME,varname,Varname) typedef SIGNATURE; @property (nonatomic,copy) TYPENAME varname; - (void) set##Varname:(TYPENAME)_

Теперь то, что требовалось ранее (для правильного автозаполнения).

typedef void(^OnEvent)(BOOL ok,id result);
@property (nonatomic,copy) OnEvent varname;
- (void) setVarname:(OnEvent)_;

просто

BlockProperty(void(^OnEvent)(BOOL ok, id result),OnEvent,varname,VarName);

ДАВНО немного проще, менее многословно, И вы получаете преимущество typedef И вам не нужно создавать неприглядное, теоретически ненужное объявление setter!

Если вы ХОТИТЕ повторно использовать «тип», вам понадобится еще один (который на этот раз будет принимать только ТРИ параметра (поскольку тип блока не может быть повторно объявлен).

#define BlockProp(TYPENAME,varname,Varname) @property (nonatomic,copy) TYPENAME varname; - (void)  set##Varname:(TYPENAME)_

BlockProp(OnEvent,anotherVar,AnotherVar);

Вы можете просто создать новый тип блока (имя) для каждого свойства, даже если их подписи совпадают (используя первый макрос), но это довольно грубо. Наслаждаться!

person Alex Gray    schedule 30.09.2014