转:http://blog.csdn.net/likendsl/article/details/7988670
最近看到很多人问一个问题,就是自定义了一个视图,视图测试的时候是可以正常使用的,但是加到工程里面去不响应点击。
其实这个问题的本质就是响应者链,你的视图控件没有被加进响应者链里,那是必然不会响应的。
至于不会被加进响应者链的情况通常是以下的情况:
1.视图本身的userInteractionEnabled为NO。这个属性是view的一个基本属性,你自定义的视图都会继承这个属性,如果你设置了这个属性为NO,或者你的父视图这个属性为NO(比如UIImage,默认情况下userInteractionEnabled=NO)。那么你的视图不会被加进响应者链也是必然的现象了。
2.你可能会说我设置了userInteractionEnabled=YES啊,这就是第二个经常出现的错误了,你确认那一句执行了么?
通常对于一个自定义的view,载入的方式有两种:
1.alloc-init的方式,这个是通过调用视图的initWithFrame函数或者init函数获得一个视图实例。
2.loadNibNamed或者xib的方式,这个方式并不会调用init和initWithFrame函数,而是调用awakeFromNib函数,换句话说,你如果在init函数中设置了userInteractionEnabled=YES,但是你是通过xib的方式来加载视图的时候,那么这句是不会执行的,是无效的。你的视图依然不会响应。
关于awakeFromNib只是增加的一个类目,让你在使用loadNibNamed的过程中可以做一些事情,和viewdidload是不同的。详细如下:
awakeFromNib
当.nib文件被加载的时候,会发送一个awakeFromNib的消息到.nib文件中的每个对象,每个对象都可以定义自己的awakeFromNib函数来响应这个消息,执行一些必要的操作。
也就是说只有通过.nib文件创建view对象时才会执行awakeFromNib 。
一般的,当IB加载的时候,我们会通过调用自定义对象的awakeFromNib函数,来对界面进行补充。
选择的时机:当你需要写一个UIView的子类并且想在load nib的时候做一些初始化工作的时候很有用。bundle在load nib后会给每个view对象发送一个awakeFromNib消息。
viewDidLoad
当view对象被加载到内存时就会执行viewDidLoad,所以不管是通过.nib文件还是以代码的方式创建对象都会执行viewDidLoad。
3.另外,还有一个,就是bounce的问题,如果你的控件在父控件的bounce之外,那么,对不起,这意味着你的控件是不会被加进去响应链的。响应事件链条的形成依赖于hitTest:withEvent:和pointInside:withEvent:函数,你可以具体的参看api来了解这两个函数以便更好地理解响应链的原理。当你的控件位于父控件的bounce之外,显示可能是视觉正常的,但是响应事件是必有问题!当你使用了背景色透明的时候,当你没有注意到控件层次的位置的时候,如果你发现你的某一个控件没法响应的话,我想,很大的可能性就是你犯了这个错误了。