EDIT2:
Нет. Предлагаемый ответ касается асинхронных вызовов. Я хочу и нуждаюсь в синхронных вызовах, например, в обычном, стандартном рекурсивном вызове.
EDIT:
а
__unsafe_unretained void (^unsafe_apply)(UIView *, NSInteger) ;
компилируется без предупреждения или ошибок, он не работает во время выполнения с NULL, хранящимся в unsafe_apply.
Однако это:
- (void) applyToView: (UIView *) view {
UIColor * (^colorForIndex)(NSInteger) = ^(NSInteger index) {
return [UIColor colorWithHue: ((CGFloat) index / 255.0f)
saturation: 0.5f
brightness: 0.5f
alpha: 1.0f] ;
} ;
void (^applyColors) (UIView *, NSInteger index) = ^(UIView * view, NSInteger index) {
view.backgroundColor = colorForIndex(index) ;
} ;
void (^__block recurse_apply)(UIView *, NSInteger) ;
void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
applyColors(view, level) ;
[view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
recurse_apply(subview, 1+level) ;
}] ;
} ;
recurse_apply = apply ;
apply(view, 0) ;
}
компилируется без предупреждений, но что более важно, на самом деле выполняется.
Но это настолько уродливое!
рассмотрим (раскраски иерархии представлений, для раскрытия цели...):
- (void) applyToView: (UIView *) view {
UIColor * (^colorForIndex)(NSInteger) = ^(NSInteger index) {
return [UIColor colorWithHue: ((CGFloat) (index * 10.0f) / 255.0f)
saturation: 0.5f
brightness: 0.5f
alpha: 1.0f] ;
} ;
void (^applyColors) (UIView *, NSInteger index) = ^(UIView * view, NSInteger index) {
view.backgroundColor = colorForIndex(index) ;
} ;
void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
applyColors(view, level) ;
[view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
apply(subview, 1+level) ;
}] ;
} ;
apply(view, 0) ;
}
Я получаю это предупреждение:
/Users/verec/Projects/solotouch/SoloTouch/BubbleMenu.m:551:42: Block pointer variable 'apply' is uninitialized when captured by block
Если я применил предложенное исправление: Maybe you meant to use __block 'apply'
void (^__block apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
Затем я получаю:/Users/verec/Projects/solotouch/SoloTouch/BubbleMenu.m:554:13: Capturing 'apply' strongly in this block is likely to lead to a retain cycle
Я пробовал различные способы подделать код и избавиться от этих предупреждений
__weak typeof (apply) wapply = apply ;
if (wapply) {
__strong typeof (wapply) sappy = wapply ;
wapply(subview, 1+level) ;
}
Но все становится хуже, превращаясь в ошибки.
Я закончил с этим:
__unsafe_unretained void (^unsafe_apply)(UIView *, NSInteger) ;
void (^apply)(UIView *, NSInteger) = ^(UIView * view, NSInteger level) {
applyColors(view, level) ;
[view.subviews enumerateObjectsUsingBlock:^(UIView * subview, NSUInteger idx, BOOL *stop) {
unsafe_apply(subview, 1+level) ;
}] ;
} ;
unsafe_apply = apply ;
apply(view, 0) ;
У кого-то есть лучшее решение, где я мог бы делать все изнутри блока, а не отвратительно возвращать его, как мне приходилось делать здесь?
Примечание. Эти qaru.site/info/327663/... Questions относятся к захвату self
, а те qaru.site/info/327663/... questions не имеют удовлетворительного ответа.