我在UIView
上写了一个允许我走视图层次结构的类别:
的UIView + capture.h中
typedef void(^MSViewInspectionBlock)(UIView *view, BOOL *stop);
@interface UIView (Capture)
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block;
@end
的UIView + Capture.m
@implementation UIView (Capture)
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block
{
BOOL stop = NO;
[self inspectViewHeirarchy:block stop:stop];
}
#pragma - Private
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block stop:(BOOL)stop
{
if (!block || stop) {
return;
}
block(self, &stop);
for (UIView *view in self.subviews) {
[view inspectViewHeirarchy:block stop:stop];
if (stop) {
break;
}
}
}
@end
您可以这样使用:
[[[UIApplication sharedApplication] keyWindow] inspectViewHeirarchy:^(UIView *view, BOOL *stop) {
if ([view isMemberOfClass:[UIScrollView class]]) {
NSLog(@"Found scroll view!");
*stop = YES;
}
}];
除了将stop
设置为YES
之外,一切正常。这似乎完全没有任何影响。理想情况下,我希望停止递归,所以当我发现视图时,我想采取一些操作,我不必继续遍历视图层次结构的其余部分。 / p>
在使用积木时,我非常密集,所以它可能是非常明显的东西。任何帮助将不胜感激。
答案 0 :(得分:4)
您使用块的方式与使用C函数完全相同。所以你真的不需要知道关于积木的事情。您的代码应该可以运行,但请注意将stop
作为BOOL *
传递给您的块并在您递归时创建新的本地区别。
您好像希望调用inspectViewHierarchy:stop:
来影响外部stop
变量。除非您将其作为参考传递,否则不会发生这种情况。所以我认为你想要的是:
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block stop:(BOOL *)stop
......以及适当的其他变化。
答案 1 :(得分:3)
我假设您希望在用户将inspectViewHierarchy
设置为stop
时从顶级YES
返回。
(顺便说一句,你拼错了“层次结构”错误,你应该在你添加到标准类的方法上使用前缀。)
@implementation UIView (Capture)
- (void)micpringle_visitSubviewsRecursivelyWithBlock:(MSViewInspectionBlock)block
{
BOOL stop = NO;
[self inspectViewHierarchy:block stop:&stop];
}
#pragma - Private
- (void)micpringle_visitSubviewsRecursivelyWithBlock:(MSViewInspectionBlock)block stop:(BOOL *)stop
{
block(self, stop);
if (*stop)
return;
for (UIView *view in self.subviews) {
[view micpringle_visitSubviewsRecursivelyWithBlock:block stop:stop];
if (*stop)
break;
}
}
@end
答案 2 :(得分:2)
- (BOOL) inspectViewHeirarchy:(MSViewInspectionBlock)block
{
BOOL stop = NO;
block(self, &stop);
if (stop)
return YES;
for (UIView *view in self.subviews) {
if ([view inspectViewHeirarchy:block])
return YES;
}
return NO;
}
答案 3 :(得分:1)
你不想在调用块后直接检查'stop'的状态吗?在调用inspectViewHierarchy之后调用它是没有用的:stop:因为你将'stop'的副本传递给该方法而不是引用。
答案 4 :(得分:0)
试试这个:
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block
{
__block BOOL stop = NO;
[self inspectViewHeirarchy:block stop:stop];
}
答案 5 :(得分:0)
块本质上会复制声明它们的变量和上下文。
即使您将布尔值作为参考传递,也可能是它使用了上下文的副本而不是真正的停止。
这只是一个疯狂的猜测,但是在inspectViewHierarchy中:stop:做类似的事情:
- (void)inspectViewHeirarchy:(MSViewInspectionBlock)block stop:(BOOL)stop
{
if (!block || stop) {
return;
}
// Add these changes
__block BOOL blockStop = stop;
block(self, &blockStop);
for (UIView *view in self.subviews) {
[view inspectViewHeirarchy:block stop:stop];
if (stop) {
break;
}
}
}
这可能是一个很长的镜头而且我不能100%确定它会在没有你的项目的情况下工作,但它值得一试。
另外,重构你的方法,所以“heirarchy”实际拼写为“层次结构”:]这对于可重用性和保持良好的代码库是好的;)