1.UIControlEventTouchDown
单点触摸按下事件:用户点触屏幕,或者又有新手指落下的时候。
2.UIControlEventTouchDownRepeat
多点触摸按下事件,点触计数大于1:用户按下第二、三、或第四根手指的时候。
3.UIControlEventTouchDragInside
当一次触摸在控件窗口内拖动时。
4.UIControlEventTouchDragOutside
当一次触摸在控件窗口之外拖动时。
5.UIControlEventTouchDragEnter
当一次触摸从控件窗口之外拖动到内部时。
6.UIControlEventTouchDragExit
当一次触摸从控件窗口内部拖动到外部时。
7.UIControlEventTouchUpInside
所有在控件之内触摸抬起事件。
8.UIControlEventTouchUpOutside
所有在控件之外触摸抬起事件(点触必须开始与控件内部才会发送通知)。
9.UIControlEventTouchCancel
所有触摸取消事件,即一次触摸因为放上了太多手指而被取消,或者被上锁或者电话呼叫打断。
10.UIControlEventTouchChanged
当控件的值发生改变时,发送通知。用于滑块、分段控件、以及其他取值的控件。你可以配置滑块控件何时发送通知,在滑块被放下时发送,或者在被拖动时发送。
11.UIControlEventEditingDidBegin
当文本控件中开始编辑时发送通知。
12.UIControlEventEditingChanged
当文本控件中的文本被改变时发送通知。
13.UIControlEventEditingDidEnd
当文本控件中编辑结束时发送通知。
14.UIControlEventEditingDidOnExit
当文本控件内通过按下回车键(或等价行为)结束编辑时,发送通知。
15.UIControlEventAlltouchEvents
通知所有触摸事件。
16.UIControlEventAllEditingEvents
通知所有关于文本编辑的事件。
17.UIControlEventAllEvents
通知所有事件
一、明确两点
1.Block可以访问Block函数以及语法作用域以内的外部变量。也就是说:一个函数里定义了一个block,这个block可以访问该函数的内部变量(当然还包括静态,全局变量),即block可以使用和本身定义范围相同的变量。
2.Block其实是特殊的Objective-C对象,可以使用copy、release等来管理内存,但和一般的NSObject的管理方式有些不同,稍后会说明。
Block很像函数指针,这从Block的语法上就可以看出。
Block的原型:
返回值 (^名称)(参数列表)
Block的定义
^ 返回值类型 (参数列表) { 表达式 }
其中返回值类型和参数列表都可以省略,最简单的Block就是:
^{ ; };
一般的定义就是:
返回值 (^名称)(参数列表) = ^(参数列表){代码段};
为了方便通常使用typedef定义:
typedef void (^blk) (void);
Block能够截获自动变量,自动变量的当前值会被拷贝到栈上作为常量,此时不能在Block内对自动变量进行赋值操作,如果有这种需求,则需要该变量是:
1.静态变量
2.全局变量
3.或者使用__block修饰符
根据Block中是否引用了自动变量,可以将Block存储区域分类:
1.__NSStackBlock__存储在栈上
2.__NSGlobalBlock__存储在全局数据区域(和全局变量一样)
3.__NSMallocBlock__存储在堆上
没有引用自动变量或者在全局作用域的Block为__NSGlobalBlock__,其他的基本上都是__NSStackBlock__。对__NSStackBlock__执行copy操作会生成__NSMallocBlock__。
一般来说出问题的Block大部分都是__NSStackBlock__,超过了__NSStackBlock__的作用域__NSStackBlock__就会销毁。
Block是C语言的扩展,C语法也可以使用Block的语法,对应的C语言使用Block_copy、Block_release。
无论是__NSStackBlock__,还是__NSGlobalBlock__,执行retain都不起作用。而__NSMallocBlock__执行retain引用计数+1。
对于copy操作,__NSStackBlock__会被复制到堆上得到一份新的__NSMallocBlock__,__NSStackBlock__还是存在的,而__NSGlobalBlock__执行copy操作不起作用。而对__NSMallocBlock__执行copy操作会引起引用计数加1。
配置在栈上的Block也就是__NSStackBlock__类型的Block,如果其所属的变量作用域结束该Block就会废弃。这个时候如果继续使用该Block,就应该使用copy方法,将__NSStackBlock__拷贝为__NSMallocBlock__。当__NSMallocBlock__的引用计数变为0,该__NSMallocBlock__就会被释放。
如果是非ARC环境,需要显式的执行copy或者antorelease方法。
而当ARC有效的时候,实际上大部分情况下编译器已经为我们做好了,自动的将Block从栈上复制到堆上。包括以下几个情况:
1.Block作为返回值时,类似在非ARC的时候,对返回值Block执行[[returnedBlock copy] autorelease];
2.方法的参数中传递Block时
3.Cocoa框架中方法名中还有useringBlock等时
4.GCD相关的一系列API传递Block时
比如:[mutableAarry addObject:stackBlock];这段代码在非ARC环境下肯定有问题,而在ARC环境下方法参数中传递__NSStackBlock__会自动执行copy,所以就不会出现问题。
对于非ARC下,为了防止循环引用,我们使用__block来修饰在Block中使用的对象。
对于ARC下,为了防止循环引用,我们使用__weak来修饰在Block中使用的对象。
原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该对象的引用计数+1。
验证__NSStackBlock__
我们往可变数组中添加一个__NSStackBlock__。
在MRC环境下,__NSStackBlock__在自身作用域结束后就从栈中释放,所以我们再次使用它的时候,程序就会发生崩溃。
在ARC环境下,编译器会自动对__NSStackBlock__执行copy,拷贝一份到堆上生成一个新的__NSMallocBlock__,我们再次使用它的时候,程序正常运行
栈(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。
全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。
文字常量区:常量字符串放在这里, 程序结束后由系统释放
程序代码区:存放函数体的二进制代码。
Block 成员需要使用 copy 进行修饰,需要考虑Block是否线程安全,必要情况下使用atomic参数,当使用atomic参数也不能百分百确保线程安全,因此在使用时最好将block属性赋值给本地变量在使用,以防止其它线程将self.block置空。实际上,我们使用修饰符 copy 是因为将存在栈区上的block转移到堆区上,这个习惯是在MRC下的,现在在ARC下使用 copy 和 strong 是相同的。
解决self循环引用的问题(ARC)
把变量在 block 外先用 __weak
声明,在 block 内把前面 __weak
声明的变量在赋值给 __strong
修饰的变量。这种写法的好处就是可以让变量在 block 内部安全使用,即使外部对象释放了,也会在 block 的生命周期内保留该变量。这种写法非常巧妙,既避免了循环引用的问题,又可以在 block 内部持有该变量。
栈(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。
全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。
文字常量区:常量字符串放在这里, 程序结束后由系统释放
程序代码区:存放函数体的二进制代码。
Block 成员需要使用 copy 进行修饰,需要考虑Block是否线程安全,必要情况下使用atomic参数,当使用atomic参数也不能百分百确保线程安全,因此在使用时最好将block属性赋值给本地变量在使用,以防止其它线程将self.block置空。实际上,我们使用修饰符 copy 是因为将存在栈区上的block转移到堆区上,这个习惯是在MRC下的,现在在ARC下使用 copy 和 strong 是相同的。
解决self循环引用的问题(ARC)
把变量在 block 外先用 __weak
声明,在 block 内把前面 __weak
声明的变量在赋值给 __strong
修饰的变量。这种写法的好处就是可以让变量在 block 内部安全使用,即使外部对象释放了,也会在 block 的生命周期内保留该变量。这种写法非常巧妙,既避免了循环引用的问题,又可以在 block 内部持有该变量。
写博客第九十九天;
QQ:565803433