OutMan——Objective-C中的ARC介绍和block的使用
2015-08-25 18:01
609 查看
ARC(Automatic Reference Counting:自动引用计数)
一、ARC的基本原理(1)ARC的判断准则:只要没有强指针指向的对象,就会释放对象(立即释放)
(2)指针分2种:
1. 强指针: __strong 默认情况下所有的指针都是强指针
2. 弱指针:__weak 当弱指针指向的对象不存在了,自动清空弱指针
二、ARC的特点
1. 不允许调用retain、release、retainCount和autorelease
2. 允许重写dealloc方法,但是不允许调用[super dealloc]
3. @property的参数
1. strong:成员变量是强指针(适用于OC对象类型)
2. weak:成员变量是弱指针(适用于OC对象类型)
3. assign:适用于非OC对象类型
4. 以前@property参数中的retain改为使用strong
三、循环引用问题
1. 比如A对象strong了B对象,B对象strong了A对象
2. 这样会导致A对象和B对象永远无法释放
四、解决ARC下循环引用的方案
一端使用strong,另一端使用week
五、ARC下解决循环引用问题的代码实现
设计要求:每个人都有一张身份证,每张身份证都代表一个人
(1)Person类的设计
Person.h文件
#import <Foundation/Foundation.h> @class Card; @interface Person : NSObject @property(nonatomic, strong)Card *card; // 身份证 @end
Person.m文件
#import "Person.h" #import "Card.h" @implementation Person - (void)dealloc { NSLog(@"Person被销毁了"); } @end
-设计注意:
1. 允许重写dealloc方法,但是不允许调用[super dealloc]
2. 解决ARC下循环引用的问题:一端使用strong,另一端使用week
(2)Card类的设计
Card.h文件
#import <Foundation/Foundation.h> @class Person; @interface Card : NSObject @property(nonatomic, weak)Person *person; // 人 @end
Card.m文件
#import "Card.h" #import "Person.h" @implementation Card - (void)dealloc { NSLog(@"Card被销毁了"); } @end
-设计注意:
1. 允许重写dealloc方法,但是不允许调用[super dealloc]
2. 解决ARC下循环引用的问题:一端使用strong,另一端使用week
(3)main.m文件
Xcode的使用技巧
一、如何查看某个项目为ARC还是MRC二、如何将MRC项目转为ARC项目
三、如何在ARC项目环境下兼容MRC文件
block的使用
一、block的基本介绍1. block用来保存一段代码
2. block的标志:^
3. block和函数很像:(1)可以保存代码(2)有返回值(3)有形参(4)调用方式一样
二、block的基本使用
(1)如何定义block变量
// 有形参有返回值的block变量的的定义 int (^sumBlock)(int, int); // 没有形参没有返回值的block变量的定义 void (^myBlock)();
(2) 如何利用block封装代码
// 利用block封装代码 sumBlock = ^(int a, int b){ return a+b; }; // 利用block封装代码 myBlock = ^(){ NSLog(@"-----------"); };
(3)如何调用
// 调用 int a = sumBlock(10, 5); NSLog(@"%d", a); // 调用 myBlock();
三、使用typedef定义block类型
四、block的使用注意
1. block内部可以访问外面的变量
2. 默认情况下block内部不能修改外部的局部变量
3. 给局部变量加上__block关键字,这个局部变量就可以在block内部被修改
五、block的深入理解
(1)深入理解一
当定义block的时候,block会把外部变量以const的方式复制一份存放到block所在的内存中,所以在默认情况下block内部不能修改外面的局部变量
(2)深入理解二
(3)深入理解三
给局部变量加上__block关键字,这个局部变量就可以在block内部修改
给局部变量加上__block关键字,当定义block的时候,block会把外部变量不再以const的方式复制一份到block所在的内存中,所以可以在block内部修改这个局部变量
(4)深入理解四
以后再使用都是堆区空间的a,不会再使用栈区空间的a
(5)深入理解五
block内部可以直接修改全局变量(全局变量不需要加__block)
六、block的应用
(1)如果一个程序员每天工作基本是固定的,那么分析使用block来实现
day1:
起床 刷牙 去车站 坐车 了解项目 去车站 坐车回家 吃饭 睡觉
day2:
起床 刷牙 去车站 坐车 分析项目 去车站 坐车回家 吃饭 睡觉
day3:
起床 刷牙 去车站 坐车 编写代码 去车站 坐车回家 吃饭 睡觉
day4:
起床 刷牙 去车站 坐车 调试项目 去车站 坐车回家 吃饭 睡觉
day5:
起床 刷牙 去车站 坐车 离职 去车站 坐车回家 吃饭 睡觉
#import <Foundation/Foundation.h> void day(void (^myblock)()) { NSLog(@"起床"); NSLog(@"刷牙"); NSLog(@"去车站"); NSLog(@"坐车"); myblock(); NSLog(@"去车站"); NSLog(@"坐车回家"); NSLog(@"吃饭"); NSLog(@"睡觉"); } void work(int n) { void (^workBlock)(); switch (n) { case 1: workBlock = ^(){ NSLog(@"了解项目"); }; break; case 2: workBlock = ^(){ NSLog(@"分析项目"); }; break; case 3: workBlock = ^(){ NSLog(@"编写代码"); }; break; case 4: workBlock = ^(){ NSLog(@"调试项目"); }; break; case 5: workBlock = ^(){ NSLog(@"离职"); }; break; default: break; } day(workBlock); } int main(int argc, const char * argv[]) { @autoreleasepool { for (int i=1; i<=5; i++) { work(i); } } return 0; }
(2)block作为函数的返回值来实现上述应用
步骤:
1. 使用typedef定义一个新的类型
2. 使用新类型作为函数的返回值
3. 定义变量接收函数的返回值(block类型)
4. 调用block
#import <Foundation/Foundation.h> typedef void (^MyBlock)(); void day(int i) { NSLog(@"起床"); NSLog(@"刷牙"); NSLog(@"去车站"); NSLog(@"坐车"); // 函数的声明 MyBlock work(int); MyBlock b = work(i); b(); NSLog(@"去车站"); NSLog(@"坐车回家"); NSLog(@"吃饭"); NSLog(@"睡觉"); } MyBlock work(int n) { MyBlock b; switch (n) { case 1: b = ^(){ NSLog(@"了解项目"); }; break; case 2: b = ^(){ NSLog(@"分析项目"); }; break; case 3: b = ^(){ NSLog(@"编写代码"); }; break; case 4: b = ^(){ NSLog(@"调试项目"); }; break; case 5: b = ^(){ NSLog(@"离职"); }; break; default: break; } return b; } int main(int argc, const char * argv[]) { @autoreleasepool { for (int i=1; i<=5; i++) { day(i); } } return 0; }
block知识点补充
一、把block作为类的属性@property(nonatomic, copy)void (^block)(); Person *p = [[Person alloc] init]; p.block = ^(){ NSLog(@"哈哈---"); }; p.block();
二、把block作为方法的参数或返回值
// block作为OC对象方法的参数 - (void)test:(void (^)())block; // block作为OC对象方法的返回值 - (void (^)())getBlock;
如果上述代码看起来别扭,可以事先通过typedef来为block定义类型
typedef void (^Block)(); // block作为OC对象方法的参数 - (void)test:(Block)block; // block作为OC对象方法的返回值 - (Block)getBlock;
实现部分和调用部分代码如下:
// 实现部分代码 // block作为OC对象方法的参数 - (void)test:(void (^)())block { if (block != nil) { block(); } } // block作为OC对象方法的返回值 - (void (^)())getBlock { return ^(){ NSLog(@"哈哈"); }; } // 调用部分代码 Person *p = [[Person alloc] init]; // 调用test方法 [p test:^(){ NSLog(@"哈哈"); }]; // 调用getBlock方法 void (^b)() = [p getBlock]; b();
—— 如果您有不同的见解,请随时指出,期待与您的交流!——
相关文章推荐
- Bug 9935857 - LOB indexes are missing from DBA_OBJECTS
- 关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
- 论文提要“Fast Feature Pyramids for Object Detection”
- QObject是QT所有类的基类
- Objective-C实现信用卡校验
- Object-C 中各数据类型转换 NSData转NSString,Byte,UIImage
- 黑马程序员——ios基础---Objective-C:对象特性、面向对象
- cloudant DB save,Not a JSON Object
- object-c 与 js交互的学习
- sysbench: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object file
- 多线程和MsgWaitForMultipleObjects
- OutMan——Objective-C内存管理
- Objective-C更改placeholder字体颜色
- Objective-C中的浅拷贝和深拷贝
- Objective-C 【@property和@synthesize关键字】
- Objective-C 【@property和@synthesize关键字】
- 用apktool反编译的时候出错:Exception in thread "main" brut.androlib.err.UndefinedResObject: resource spec:
- UVA - 1161 Objective: Berlin(最大流+时序模型)
- Object -C NSNumber -- 笔记
- [Objective-C]类与对象