蓝懿ios技术交流和心得分享16.1.17

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的定义

^ 返回值类型 (参数列表) { 表达式 }

其中返回值类型和参数列表都可以省略,最简单的Block就是:

^{ ; };

一般的定义就是:

返回值 (^名称)(参数列表) = ^(参数列表){代码段};

为了方便通常使用typedef定义:

typedef void (^blk) (void);

三、Block存储域

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执行retain,copy方法的效果

Block是C语言的扩展,C语法也可以使用Block的语法,对应的C语言使用Block_copy、Block_release。

无论是__NSStackBlock__,还是__NSGlobalBlock__,执行retain都不起作用。而__NSMallocBlock__执行retain引用计数+1。

对于copy操作,__NSStackBlock__会被复制到堆上得到一份新的__NSMallocBlock__,__NSStackBlock__还是存在的,而__NSGlobalBlock__执行copy操作不起作用。而对__NSMallocBlock__执行copy操作会引起引用计数加1。

五、什么时候要对__NSStackBlock__执行copy操作?

配置在栈上的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,所以就不会出现问题。

六、Block的循环引用

对于非ARC下,为了防止循环引用,我们使用__block来修饰在Block中使用的对象。

对于ARC下,为了防止循环引用,我们使用__weak来修饰在Block中使用的对象。

原理就是:ARC中,Block中如果引用了__strong修饰符的自动变量,则相当于Block对该对象的引用计数+1。

七、代码验证

验证__NSStackBlock__

我们往可变数组中添加一个__NSStackBlock__。

在MRC环境下,__NSStackBlock__在自身作用域结束后就从栈中释放,所以我们再次使用它的时候,程序就会发生崩溃。

在ARC环境下,编译器会自动对__NSStackBlock__执行copy,拷贝一份到堆上生成一个新的__NSMallocBlock__,我们再次使用它的时候,程序正常运行

 


栈(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

堆(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。

全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。

文字常量区:常量字符串放在这里, 程序结束后由系统释放

程序代码区:存放函数体的二进制代码。

程序示例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int a = 0 ; //全局初始化区
char * p1 ; //全局未初始化区
main ( )
     {
         int b ; //栈
         char s [ ] = "abc" ; //栈
         char * p2 ; //栈
         char * p3 = "123456" ; //123456\0在常量区,p3在栈上。
         static int c = 0//全局(静态)初始化区
         p1 = ( char * ) malloc ( 10 ) ;
         p2 = ( char * ) malloc ( 20 ) ;
         //分配得来得10和20字节的区域就在堆区。
         strcpy ( p1 , "123456" ) ; //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

 

Block基本语法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//As a local variable:
returnType ( ^ blockName ) ( parameterTypes ) = ^ returnType ( parameters ) { ... } ;
As a property :
 
//As a property:
@ property ( nonatomic , copy ) returnType ( ^ blockName ) ( parameterTypes ) ;
As a method parameter :
 
//As a method parameter:
- ( void ) someMethodThatTakesABlock : ( returnType ( ^ ) ( parameterTypes ) ) blockName ;
As an argument to a method call :
 
//As an argument to a method call:
[ someObject someMethodThatTakesABlock : ^ returnType ( parameters ) { ... } ] ;
As a typedef :
 
//As a typedef:
typedef returnType ( ^ TypeName ) ( parameterTypes ) ;
TypeName blockName = ^ returnType ( parameters ) { ... } ;

 

修饰Block的成员变量

Block 成员需要使用 copy 进行修饰,需要考虑Block是否线程安全,必要情况下使用atomic参数,当使用atomic参数也不能百分百确保线程安全,因此在使用时最好将block属性赋值给本地变量在使用,以防止其它线程将self.block置空。实际上,我们使用修饰符 copy 是因为将存在栈区上的block转移到堆区上,这个习惯是在MRC下的,现在在ARC下使用 copy 和 strong 是相同的。

解决self循环引用的问题(ARC)

1
__weak __typeof ( self ) weakSelf = self ;

 

AFNetworking的使用技巧

 

1
2
3
4
5
6
7
8
9
10
MyObject * obj = [ [ MyObject alloc ] init ] ;
obj . text = @ "string" ;
__weak MyObject * weakObj = obj ;
dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ) , ^ {
     __strong MyObject * strongObj = weakObj ;
     sleep ( 3 ) ;
} ) ;
sleep ( 1 ) ;
obj = nil ;
sleep ( 4 ) ;

把变量在 block 外先用 __weak 声明,在 block 内把前面 __weak 声明的变量在赋值给 __strong 修饰的变量。这种写法的好处就是可以让变量在 block 内部安全使用,即使外部对象释放了,也会在 block 的生命周期内保留该变量。这种写法非常巧妙,既避免了循环引用的问题,又可以在 block 内部持有该变量。

栈(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

堆(heap): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式类似于链表。

全局区(静态区static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域,程序结束后由系统释放。

文字常量区:常量字符串放在这里, 程序结束后由系统释放

程序代码区:存放函数体的二进制代码。

程序示例

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int a = 0 ; //全局初始化区
char * p1 ; //全局未初始化区
main ( )
     {
         int b ; //栈
         char s [ ] = "abc" ; //栈
         char * p2 ; //栈
         char * p3 = "123456" ; //123456\0在常量区,p3在栈上。
         static int c = 0//全局(静态)初始化区
         p1 = ( char * ) malloc ( 10 ) ;
         p2 = ( char * ) malloc ( 20 ) ;
         //分配得来得10和20字节的区域就在堆区。
         strcpy ( p1 , "123456" ) ; //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

 

Block基本语法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//As a local variable:
returnType ( ^ blockName ) ( parameterTypes ) = ^ returnType ( parameters ) { ... } ;
As a property :
 
//As a property:
@ property ( nonatomic , copy ) returnType ( ^ blockName ) ( parameterTypes ) ;
As a method parameter :
 
//As a method parameter:
- ( void ) someMethodThatTakesABlock : ( returnType ( ^ ) ( parameterTypes ) ) blockName ;
As an argument to a method call :
 
//As an argument to a method call:
[ someObject someMethodThatTakesABlock : ^ returnType ( parameters ) { ... } ] ;
As a typedef :
 
//As a typedef:
typedef returnType ( ^ TypeName ) ( parameterTypes ) ;
TypeName blockName = ^ returnType ( parameters ) { ... } ;

 

修饰Block的成员变量

Block 成员需要使用 copy 进行修饰,需要考虑Block是否线程安全,必要情况下使用atomic参数,当使用atomic参数也不能百分百确保线程安全,因此在使用时最好将block属性赋值给本地变量在使用,以防止其它线程将self.block置空。实际上,我们使用修饰符 copy 是因为将存在栈区上的block转移到堆区上,这个习惯是在MRC下的,现在在ARC下使用 copy 和 strong 是相同的。

解决self循环引用的问题(ARC)

1
__weak __typeof ( self ) weakSelf = self ;

 

AFNetworking的使用技巧

 

1
2
3
4
5
6
7
8
9
10
MyObject * obj = [ [ MyObject alloc ] init ] ;
obj . text = @ "string" ;
__weak MyObject * weakObj = obj ;
dispatch_async ( dispatch_get_global_queue ( DISPATCH_QUEUE_PRIORITY_DEFAULT , 0 ) , ^ {
     __strong MyObject * strongObj = weakObj ;
     sleep ( 3 ) ;
} ) ;
sleep ( 1 ) ;
obj = nil ;
sleep ( 4 ) ;

把变量在 block 外先用 __weak 声明,在 block 内把前面 __weak 声明的变量在赋值给 __strong 修饰的变量。这种写法的好处就是可以让变量在 block 内部安全使用,即使外部对象释放了,也会在 block 的生命周期内保留该变量。这种写法非常巧妙,既避免了循环引用的问题,又可以在 block 内部持有该变量。

  • 学习ios  重要还是要理清楚思路  在做或者看老师代码的时候 自己多想想为什么  不要自己看着就抄       另外还是要推荐一下 蓝懿IOS这个培训机构  和刘国斌老师刘国斌老师还是很有名气的,听朋友说刘老师成立了蓝懿iOS,,老师讲课方式很独特,能够尽量让每个人都能弄明白,有的比较难懂的地方,如果有的地方还是不懂得话,老师会换个其它方法再讲解,这对于我们这些学习iOS的同学是非常好的,多种方式的讲解会理解得更全面,这个必须得给个赞,嘻嘻,还有就是这里的学习环境很好,很安静,可以很安心的学习,安静的环境是学习的基础,小班讲课,每个班20几个学生,学习氛围非常好,每天都学到9点多才离开教室,练习的时间很充裕,而且如果在练习的过程中有什么困难,随时可以向老师求助,不像其它机构,通过视频教学,有的甚至学完之后都看不到讲师本人,问点问题都不方便,这就是蓝懿与其它机构的区别,相信在刘国斌老师的细心指导下,每个蓝懿学员都能找到满意的工作,加油!

                                                                      写博客第九十九天;

                                                                                  QQ:565803433

  • 你可能感兴趣的:(蓝懿ios技术交流和心得分享16.1.17)