Я пытаюсь создать хороший инициализатор на основе блоков для класса object-c. Я объявляю его в суперклассе, и я хочу, чтобы он был полезен во всех подклассах.Динамическая модификация блока во время выполнения
Прямо сейчас у меня есть:
+ (id)createWithBlock:(void (^) (id newObject))creationBlock {
id newObject = [self object];
creationBlock(newObject);
return newObject;
}
который может быть использован (в подклассе), как, например:
Record *newRecord = [Record createWithBlock:^(id newObject) {
Record *newRecord = (Record *)newObject;
newRecord.name = @"Ginger";
newRecord.type = @"Rhizome";
}];
Это нормально сейчас, но я хотел бы, чтобы это сравнению немного вниз. В идеале это выглядело бы так:
Record *newRecord = [Record createWithBlock:^{
name = @"Ginger";
type = @"Rhizome";
}];
Но это кажется немного амбициозным. Я также хотел бы быть в порядке только с:
Record *newRecord = [Record createWithBlock:^(Record *newRecord) {
newRecord.name = @"Ginger";
newRecord.type = @"Rhizome";
}];
Эта последняя версия трудно, потому что кажется лязг делает некоторый тип проверки времени компиляции для блоков. Вышеупомянутое не будет компилироваться с определением createWithBlock: что у меня выше, потому что: incompatible block pointer types initializing 'void (^)(struct Record *)', expected 'void (^)(struct objc_object *)
.
Если он не сделал этого сильного типа проверки, я мог бы просто swizzle методы во время выполнения. (Или, может быть, я мог бы это сделать прямо сейчас, если бы я напечатал объявление в блоке?)
Я немного почесываю голову, и я прочитал почти каждый документ о блоках, которые я мог найти, в том числе спецификация clang. Если у кого-то есть идеи, которые я бы хотел их услышать, это для проекта с открытым исходным кодом, и я думаю, что эта модель принесет пользу всем пользователям с объективными-c.
Прямо сейчас мои мысли склоняются к imp_implementationWithBlock()
. Но тогда мне нужно будет «построить» новый IMP, основанный на том, что в нем, и замените его. Реализуемое?
Точно, что это достигается за просто инициализацию свойств * после * конструктора? (Независимо от того, что я просто проглотил подробный синтаксис, пока Apple не захочет добавить в ObjC дженерики, это идиома, которая не удивит людей, использующих ваш API.) – millimoose
Это скорее стиль/читаемость, чем функциональность. Путем инициализации всего в блоке есть визуальное представление объекта, находящегося в одном месте на экране. И для более сложных инициализаций это мне кажется полезным. (Многие другие языки имеют такой тип создания). EDIT: Несколько других языков. –
Возможно, вместо того, чтобы определять один инициализатор в суперклассе, вы можете заставить макрос препроцессора генерировать определение типов для третьего варианта синтаксиса для вас. Немного котельная, но кажется разумным немагическим компромиссом. – millimoose