viewWithTag获取subview规则详解

原文;http://www.cnblogs.com/smileEvday/archive/2012/03/21/2410529.html

获取subview

  通常我们在view层级里面对subView的操作可以通过两种方式:1、保留一个subview的引用,然后在类中通过该引用对该subview进行操作,但是要注意在适当的位置添加内存维护的代码,退出前手动释放。2、设置subview的Tag,让后在要使用的时候,通过viewWithTag获取到相应的subview,这种方法比较简洁,也不用自己去维护内存。

  ViewWithTag: 通常采用深度遍历优先的算法,返回第一个tag和给定Tag相等的subview。这就导致了一个当一个view的多个subview的tag相同的时候,我们通过该方法得到的view可能并不是自己想要的。

  下面通过一个小例子验证一下,代码如下:

SvTestViewTag.h
SvTestViewWithTag.m

  例子中代码创建的view的层次图如下:

 

   例子中每个subview都是一个UILabel,而且设置了相应的内容。按钮的响应函数的实现思路:首先隐藏所有类型为UILabel的subview(排除UIButton,因为button需要一直显示),然后根据指定的Tag获取到相应的subview,该subview及其superView的hidden属性为NO。这样就可以保证点击按钮的时候只显示的是第一个tag和指定tag相等的subview。

  为了验证viewWithTag获取subview的原理:

  首先我在subview1中添加了两个tag都为11的subview11和subview12。 运行程序可以,当我们点击"Show Tag 11"按钮的时候屏幕上将显示“SubView11”,而非“SubView12”。同时不管你点击几次该按钮,始终只显示“SubView11”。这样可以看出来同一层级中获取subview时候查找顺序为index从小到大的原则,即位于相对下层的将首先被找到。

  其次我还在subview1中添加了tag均为13的subview13,同时向view中添加了tag也为13的subview2,运行程序点击“Show Tag 13”按钮,屏幕上将会显示“SubView13”,而非“SubView2”。这可以验证viewWithTag在搜索的时候遵循深度优先遍历的原则,即会首先查找最下层的view并递归查询其subview。

  综上两点我们可以看出来viewWithTag获取subview的基本原则,即遵循深度优先,下层优先两个原则。

 

PS:在测试的时候我也发现只要点击过“Show Tag 13”以后,再点击“Show Tag 11”将失去效果,不知道什么原因,但是重启程序就会恢复正常。

  期待你们的答案!

 

Subview的事件响应

原文:http://www.cnblogs.com/smileEvday/archive/2012/03/22/2410715.html

  在view的层级里面,默认情况下subview是可以显示到其父view的frame区域以外的,通过设置clipToBounds属性为YES,可以限制subview的显示区域。但是touch在各个UIView中传递的时候,区域时限制在view的frame内,此处包含两个信息:1、在当前view的frame以外所做的操作是不会传递到该view中的,这一点很容易理解。2、如果touch事件是发生在当前view的frame以外,该view所有的subview将也不会再收到该消息。这一点通常容易被我们忽略,很多奇怪的问题就是这个引起的。

  下面请看一个小例子,定制view的代码如下:

复制代码
//
//  SvTestClipSubviewEvent.h
//  SvUIViewSample
//
//  Created by maple on 3/19/12.
//  Copyright (c) 2012 smileEvday. All rights reserved.
//
//  默认的情况下,subView可以超出父view的frame,即可以显示到父View的外边
//  但是消息的接受返回却是由于父View的大小限制,即出了父View的subView将不能收到消息
//  在程序中一定要注意当前程序view的最底层是充满整个window的可用区域的,
//  否则将会导致某些区域明明有按钮但是却点不中的问题

#import <UIKit/UIKit.h>

@interface SvTestClipSubviewEvent : UIView

@end
复制代码
SvTestClipSubviewEvent.m

  在程序的ViewController中添加如下测试代码:

SvTestClipSubviewEvent *testClipSubView = [[SvTestClipSubviewEvent alloc] initWithFrame:CGRectMake(100, 100, 150, 150)];
[self.view addSubview:testClipSubView];
[testClipSubView release];

  运行可以看到如下界面:

  该例子中我们设置定制view的背景颜色为红色,然后创建一个位于定制view外的UIButton “I'm out”以及另一个位于定制view内的UIButton “I‘m in”。运行程序,我们可以发现点击"I'm out"按钮时界面根本没有变化,在btnAction:函数中加断点,也不会进去,这就说明该按钮根本没有接受到消息,同时“I'm in”按钮运行正常,点击后控制台会输出信息“...UIViewSample[664:f803] HI, you tap button I'm in”。这些可以说明subview接收事件的范围是受其superview的frame闲限制的,不可能接受到superview的frame以外的touch事件。

  如果我们的程序有些时候看着一些按钮明明正常但是却不能正常接收touch消息的时候,可能就是其显示位置已经跑出了superview的frame范围了。所以程序的rootview一定要时刻充满整个window,否则就可能导致程序的某些地方不能正常相应用户消息。同时建议对于那些只是充当容器的view,最好设置autoresizingMask的值为UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight,这样当其superview的大小发生变化时候就会自动缩放至superview一样大小,保证每一刻都充满其superview,从而避免因显示位置出界导致的不能正常相应用户touch事件等问题。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值