Я пишу API, который включает обработку событий, и я хотел бы иметь возможность использовать блоки для обработчиков. Обратные вызовы часто хотят получить доступ или изменить себя. В режиме ARC Clang предупреждает, что блоки, ссылающиеся на self, скорее всего, создадут цикл сохранения, который кажется полезным предупреждением, которое я хочу продолжать в целом.
Однако для этой части моего API жизненный цикл обратного вызова и содержащий объект поддерживаются извне. Я знаю, что могу разрушить цикл, когда объект должен быть освобожден.
Я могу отключить предупреждение цикла сохранения для каждого файла с помощью #pragma clang diagnostic ignored "-Warc-retain-cycles"
, но это отключает предупреждение для всего файла. Я могу окружать блоки с помощью #pragma clang diagnostic push
и pop
вокруг этого предупреждения, но это делает блоки уродливыми.
Я также могу заставить предупреждение уйти, ссылаясь на переменную __weak, указывающую на себя, вместо того, чтобы напрямую ссылаться на ядро, но это делает блоки намного менее приятными в использовании.
Лучшим решением, которое я придумал, является этот макрос, который отключает диагностику вокруг блока:
#define OBSERVE(OBJ, OBSERVEE, PATH, CODE) \
[(OBJ) observeObject:(OBSERVEE) forKeyPath:(PATH) withBlock:^(id obj, NSDictionary *change) { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-retain-cycles\"") \
do { CODE; } while(0); \
_Pragma("clang diagnostic pop") \
}];
Это работает, но это не очень доступно для пользователей API, он не позволяет вложенным наблюдателям, и он плохо взаимодействует с редактором XCode. Есть ли лучший способ отключить или избежать предупреждения?