iOS之《Effective Objective-C 2.0》读书笔记(1)

来源:互联网 发布:中原工学院网络 编辑:程序博客网 时间:2024/05/18 00:59

前言:

1.目标读者:本书面向有志于深入研究Objective-C的开发者,帮助其完全发挥出这门语言的优势,以编写便于维护,执行迅速且不易出错的代码(不适用于iOS入门)
2.本书七章共有52条实用技巧,接下来我将逐一把这52条技巧的精髓通过博客展现出来,分享给大家,如有不足,望指正

第一条:了解Objective-C的起源

1.OC消息结构 vs C++函数调用:
(1)代码展现:

// 消息结构Object *obj = [Object new];[obj performWith:parameter1 add:parameter2];// 函数调用Object *obj = new Object;obj->performm(parameter1,parameter2);

(2)核心区别:前者运行时执行的代码由运行环境决定,后者由编译器决定
2.OC与C的关系:
(1)OC是C的超集:在OC中可以使用C的所有代码
(2)内存管理:OC对象存储在堆上,且需要自己管理,即引用计数,指针存储在栈上,它会自己管理内存

NSString *someString = @"Hello World";NSString *anotherString = someString;

堆栈

延伸学习:

1.动态绑定:
1》需要了解的概念:
(1)动态绑定:一个对象内否调用指定的方法不是由编译器决定而是由运行时决定
(2)isa实例变量:任意NSObject的子类都会继承NSObject的isa实例变量,而且当NSObject的子类实例化对象时,isa实例变量永远是对象的第一个实例变量。
(3)Objetive-C中的Method结构

struct objc_method{SEL method_name;//方法名char *method_types; //方法地址IMP method_imp; //方法地址(IMP)};typedefobjc_method Method;

(4)IMP是”implementation”的缩写,它是objetive-C 方法 (method)实现代码块的地址,类似函数指针,通过它可以 直接访问任意一个方法。免去发送消息的代价。

SEL print_sel =NSSelectorFromString(@“print:”);//获得SELIMP imp=[person methodForSelector:print_sel];//得到IMPimp(person,print_sel,@“*********”);//通过IMP直接调用方法 ,imp的第一参数是对象自己(self),第二参数是方法标示, 第三个是方法的参数等效调用:[person print_sel:@“*********”];

(5)消息映射表:运行时系统会缓存消息映射表,这样会加大查找速度

2》过程:消息 表达式为: [reciver message];
(1)首先通过第一个参数的receiver,找到它的isa 指针,然 后在isa 指向的Class 对象中使用第二个参数selector 查 找方法;
(2)如果没有找到,就使用当前Class 对象中的新的isa 指针 到上一级的父类的Class 对象中查找;
(3)当找到方法后,再依据receiver 的中的self 指针找到当前 的对象,调用当前对象的具体实现的方法(IMP),然后传 递参数,调用实现方法。
(4)假如一直找到NSObject 的Class 对象,也没有找到你调 用的方法,就会报告不能识别发送消息的错误。
(5)再次运行时会有先从缓存消息映射表中加载信息

// 相关方法:【receiver message】;—>objc_msgSend(receiver,message);—>objc_msgSendSuper(receiver,message);

3》动态绑定的应用:

 -isMemberOfClass:    判断是否是这个类的实例    -isKindOfClass:    判断是否是这个类或者这个类的子类的实例    -respondsToSelector:    判读实例是否有这样方法    +instancesRespondToSelector:    判断类是否有这个方法。此方法是类方法。

2.内存管理:
1》为什么需要内存管理?

只有OC对象才需要管理内存,非OC对象(如:charint、folat)则不需要管理内存的本质原因:OC对象是放在堆内存里,非OC对象是放在栈内存里,栈内存里的东西系统会自动管理

2》内存管理相关的三个概念:
(1)引用计数:对象.retainCount

  1)当对象被创建(通过alloc、new或copy等方法)时,其引用计数初始值为1 2)給对象发送retain消息,其引用计数加1 3)給对象发送release消息,其引用计数减1 4)当对象引用计数归0时,ObjC給对象发送dealloc消息销毁对象

 
(2)自动释放池

问题:这三种写法有什么区别吗?// 不添加:for (long i = 0; i < largeNumber; ++i) {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];    }// 内部:for (long i = 0; i < largeNumber; ++i) {        @autoreleasepool {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];        }}// 外部: @autoreleasepool {        for (long i = 0; i < largeNumber; ++i) {            NSString *str = [NSString stringWithFormat:@"hello - %ld", i];            str = [str uppercaseString];            str = [str stringByAppendingString:@" - world"];        }    }答案:(1)不加autorelease开辟的内存是不会释放的     (2)内部略微快一点,但这是取决于编译器     (3)开发中,通常在内部添加

(3)属性的内存管理

1.atomic 和 nonatomic1)atomic:表示对对象的操作属于原子操作,支持多线程,使用atomic比nonatomic更耗费系统资源。(2nonatomic 表示访问器的访问不是原子操作,不支持多线程访问安全,但是访问性能高。(3)原因:在多线程的下对对象的访问都需要先上锁访问后再解锁,保证不会同时有几个操作针对同一个对象,所以多线程访问的情况下,会耗费资源,降低性能2.retain,assign和copy(1assign:只可以对基本数据类型(如CGFloatNSInteger,Bool,int,代理对象)等使用。该方式会对对象直接赋值而不会进行retain操作(2)retain :使对象的应用计数增加一(3)copy :表示重新建立一个新的计数为1的对象,然后释放掉旧的值(4)原因:retain是对指针的拷贝,copy是对内容的拷贝     比如:NSString 对象的地址为0x100,其内容为“string”,如果使用copy到另外一个NSString对象,则会生成另外一个地址为0x110的对象,只不过内容仍然是‘string“。如果使用retain到另外一个NSString对象,则该对象的地址仍然为0x100,只不过该对象的计数变为2.3.strongweak1strong 强引用,strong修饰的属性一般不会自动释放。默认的所有实例变量和局部变量都是strong指针。   eg1: @property (nonatomic, strong) NSArray *dataList;@property (nonatomic, strong) UILabel *label;   eg2: 使用懒加载定义控件的时候,一般也用strong   eg3:addSubView 默认对其 subView 进行了强引用(2weak 弱引用,主要用于防止循环引用   eg1: 使用 sb 或者 xib 给控件拖线的时候: @property (weak, nonatomic) IBOutlet UILabel *label;   eg2: delegate模式,你的ViewController通过strong指针(self.view)拥有一个UITableView, UITableView的dataSource和delegate都是weak指针,指向你的ViewController。
阅读全文
0 0