我们知道一个view可以通过tag标记,并且父类的view可以通过viewWithTag: 找到对应的子view。但是使用viewWithTag时也有一些注意点。
我们来看下苹果SDK里的注释
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag; // recursive search. includes self
注释的意思是递归查找tag,包括判断view本身的tag是否和传入的tag相同。那么问题来了,当view的tag和它的子view的tag的值相同的时候返回值是它自身呢?还是它的子view呢?,如果它有两个相同tag的子view,应该返回哪个呢?
回答这个问题之前首先我们来做个试验, 假设我们有一个view A, A有两个子view B1、B2,B1、B2又分别有子view C1、C2、C3、C4,他们对应的tag值为各字母后面的值.如图1所示
A 10
- B1 11
- C1 12
- C2 13
- B2 12
- C3 10
- C4 11

当我们执行下面的代码:
NSInteger tag = 10;
UIView *view = [self.viewA viewWithTag:tag];
view.backgroundColor = [UIColor blueColor];
// view A变成蓝色
NSInteger tag = 11;
UIView *view = [self.viewA viewWithTag:tag];
view.backgroundColor = [UIColor blueColor];
// view B1变成蓝色
NSInteger tag = 12;
UIView *view = [self.viewA viewWithTag:tag];
view.backgroundColor = [UIColor blueColor];
// view C1变成蓝色
NSInteger tag = 13;
UIView *view = [self.viewA viewWithTag:tag];
view.backgroundColor = [UIColor blueColor];
// view C2变成蓝色
通过以上几个例子我们可以知道一个view 调用viewWithTag:方法,这个方法会查找view自身的tag、子view的tag、子view的子view的tag,等等。
而viewWithTag:方法遍历的顺序是先查找自身、然后递归查找某一子view的viewWithtag:,如果找到则返回这个view, 如果都没找到则返回nil。直到将这一分支的所有的view都查找完毕再查找下一个子view。类似于下面的代码
- (UIView *)viewWithTag:(NSInteger)tag
{
// 如果自己的tab符合要求,就返回自己
if (self.tag == tag) {
return self;
}
// 遍历子控件(也包括子控件的子控件), 直到找到符合条件的子控件为止
for (UIView *subview in self.subviews) {
UIView *resultView = [subview viewWithTag:tag];
if (resultView) {
return resultView;
}
}
return nil;
}
上面就是viewWithTag:本人理解的原理,如有错误的地方欢迎大家指出。
网友评论