Я пишу API, который включает обработку событий, и я хотел бы иметь возможность использовать блоки для обработчиков. Обратные вызовы часто хотят получить доступ или изменить себя. В режиме ARC Clang предупреждает, что блоки, ссылающиеся на себя, могут создать цикл сохранения, что кажется полезным предупреждением, которое я хочу сохранить в общем.
Однако для этой части моего 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. Есть ли лучший способ отключить или избежать предупреждения?