Effective Object-c 2.0 读书笔记
程序员文章站
2022-05-13 12:45:40
OC 的简单实用
1.在类的头文件中尽量少引用其他头文件
#import 和 @class 后者不需要知道类的全部细节,只是知道有一个类名叫XXX(避免循环饮用,两个类中有...
OC 的简单实用
1.在类的头文件中尽量少引用其他头文件
#import 和 @class 后者不需要知道类的全部细节,只是知道有一个类名叫XXX(避免循环饮用,两个类中有一个无法被正确编译) 向前声明(@class)能降低编译时间,还能降低彼此依赖程度2.多用字面量语法,少用与之等价的方法
字面量数值 NSString *string = @"text"; NSNumber *number = @2.5; NSNumber *boolNumber = @YES; 字面量数组(确保不能有nil) NSSArray *animal = @["cat", "dog", "fish"]; NSSString *str = animal[1]; 字面量字典(确保不能有nil) NSDictionary *dic = @{@"key": @"Value",@"key1": @"Value1"}
3.多用类型常量,少用#define预处理指令
define ANIMATION_DURTION 0.3 static const NSTimerINterval KAnimationDurtion = 0.3(若只局限于编译单元前面?K,若全局通常以类名为前缀) 使用全局变量
//XXX.h extern NSString *const xxxStringConstant // XXX.m NSString *const xxxStringConstant = @"Value"
4.用枚举表示状态、选项、状态码
4.用枚举表示状态、选项、状态码
状态机、选项卡 某个方法的选项定义为枚举类型,而多个选项又可以同时使用的,将各选项值定义为2的幂 处理枚举类型的switch语句不使用default分支
对象、消息、运行期
对象、消息、运行期
1.理解“属性”这一概念
1.理解“属性”这一概念
getter、setter、autosynthesis(会在编译期执行合成方法)、synthesis(修改变量名:_xxx) copy(为了安全)、strong、weak、assign(简单赋值)、nonatomic、atomic(太耗性能)
2.在对象内部尽量直接访问实例变量
2.在对象内部尽量直接访问实例变量
//xxx.h @property (copy, nonatomic) NSString * firstName Xcode会自动为你autosynthesis 生成相应get、set 方法 _firstName 是直接访问实例变量 self.firstName 是访问方法返回变量
3.理解”对象等同性”这一概念
3.理解”对象等同性”这一概念
若想检测对象的等同性
- (BOOL)isequalToPerson:(Person *)otherPerson { if (self == otherPerson) return YES; if (!([_firstName isEqualToString:otherPerson.firstName])) { return NO; } return YES; }
相同的对象必须具有相同的hash,但是两个哈希码相同的对象未必相同
hashcode本身就是个函数,是可以重载的,你完全可以写个函数总是返回固定值。但hashcode函数从设计要求上来说,要尽量保证:不同对象的hashcode不同。
尽量使用计算速度快而且哈希码碰撞几率低的算法
4.以”类族模式”隐藏实现细节(后续补充)
4.以”类族模式”隐藏实现细节(后续补充)
子类应该继承自类族中的抽象基类 子类应该定义自己的数据存储方式(?) 子类应该覆写超类文档中需指明需要覆写的方法 类族模式可以把实现细节隐藏在一套简单的公共接口后面 系统框架中经常使用类族 从类族的公共抽象基类中继承自类时要当心,若有开发文档,则应首先阅读
5.在即有类中使用关联对象存放自定义数据
5.在即有类中使用关联对象存放自定义数据
(Runtime的使用)
OBJC_ASSOCIATION_ASSIGN OBJC_ASSOCIATION_RETAIN_NONATOMIC OBJC_ASSOCIATION_COPY_NONATOMIC OBJC_ASSOCIATION_RETAIN OBJC_ASSOCIATION_COPY
6.理解objc_msgSend的作用
6.理解objc_msgSend的作用
消息由接受者、选择子及参数构成。给某对象”发送消息”(invoke a message),就相当于在该对象上”调用方法” 发给某对象的全部消息都要由”动态派发系统”来处理,该系统会查出对应的方法,并执行其代码。
7.理解消息转发机制
7.理解消息转发机制
若对象无法响应某个选择子,则进入消息转发过程
+ (BOOL)resolveInstanceMethod:(SEL)sel { NSString *selectorString = NSStringFromSelector(sel); if ([selectorString hasPrefix:@"set"]) { class_addMethod(self, sel, (IMP)autoDictionarySetter, "v@:@"); } else { class_addMethod(self, sel, (IMP)autoDictionaryGetter,"@ @:"); } return YES; }
8.用”方法调配技术”调试”黑盒方法”
8.用”方法调配技术”调试”黑盒方法”
使用另一份实现来替换原有的方法实现 不宜乱用
9.理解”类对象”的用意
9.理解”类对象”的用意
每个实例都有一个指向class对象的指针,用以表明其类型,而这些class对象则构成了累的继承体系 如果对象无法在编译器确定,那么就应使用类型方法来探知。 尽量使用类型查询方法。而不要直接比较对象,因为某些对象可能实现了消息转发功能(?)
isKindOfClass isMemberOfClass NSLog(@"%@",NSStringFromClass([NSDictionary class])); //print : NSDictionary NSLog(@"%@",NSStringFromClass([[NSMutableDictionary new]class])) //print : __NSDictionaryM
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; NSLog(@"%d,%d, %d",[dic isMemberOfClass:[NSDictionary class]], [dic isMemberOfClass:[NSMutableDictionary class]], [dic isMemberOfClass:NSClassFromString(@"__NSDictionaryM")]); 输出 001
接口与API设计
接口与API设计
1.用前缀避免命名空间冲突
1.用前缀避免命名空间冲突
选择与你公司、应用程序或者两者皆有关联之名称作为类名的前缀,并在所有代码使用这一前缀 若自己所开发的程序库用到了第三方库,则应为其中的名称加上前缀
2.提供”全能初始化方法”
2.提供”全能初始化方法”
在类中提供一个全能初始化方法,并于文档里指明。其他初始化方法均应调用此方法 若全能初始化方法与超类不同,则需要覆盖超类中的对应方法 若超类的初始化方法不适用于自类,那么应该覆写超类这个放啊。并在其中抛出异常
- (instancetype)init { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"必须使用 initFirstName:" userInfo:nil]; }
3.实现description方法
3.实现description方法
4.尽量使用不可变对象(??)
4.尽量使用不可变对象(??)
尽量创建不可变的对象 若某属性仅可用于对象内部修改,则在”class-cintinuation分类”中将其由readonly属性扩展为readwrite。 不要把可变的collection作为属性公开,而应提供相关方法,以此修改对象的可变对象
5.使用清晰而协调的命名方式
5.使用清晰而协调的命名方式
in、for、with、and、has、is 驼峰式(类的首字母要大写并且带前缀,方法首字母小写) 方法名要言简意赅,从左至右像是日常用语 方法不要带缩略后的类型名称
6.为私有方法名加前缀
6.为私有方法名加前缀
给私有方法的名称加上前缀,这样可以很容易的将其同公共方法区分开 不要单用一个下划线做私有方法的前缀,因为这种做法是预留给苹果公司使用
7.理解Object-C的错误模型
7.理解Object-C的错误模型
只有发生了可使整个应用程序崩溃的严重错误时,才应使用异常 若错误不那么严重的话,可以将错误信息放在NSError对象里,经由”输出参数”返回给调用者
8.理解NSCopying协议
8.理解NSCopying协议
可变对象调用copy方法会返回一个不可变类的实例
不可变对象调用mutableCopy方法会反悔一个不可变版本
若想令自己所写的对象具有拷贝功能,则需实现NSCopying协议
协议和分类
协议和分类
1.通过委托与数据源协议进行对象间通信
1.通过委托与数据源协议进行对象间通信
if([_delegate resondsToSelector:@selector(xxx:xxx)]) { do something } *更好的是使用struct*
2.将类的实现代码分散到便于管理的数个分类之中
2.将类的实现代码分散到便于管理的数个分类之中
使用分类机制把类的实现代码分成易于管理的小块 将应该视为”私有”的方法归入Private的分类中,以隐藏实现细节
3.总是为第三方类的分类名称加前缀(??)
3.总是为第三方类的分类名称加前缀(??)
向第三方类中添加分类,总应给其名称加上你专用的前缀 向第三方类中添加分类时,总应给其中的方法加上你专用的前缀
4.勿在分类中声明属性
4.勿在分类中声明属性
把封装数据所用的全部属性都定义在主接口(如果是扩展NSObject,那就必须是Runtime) 在”class-continuation分类”之外的其它分类,可以定义存取方法,但尽量不要定义属性
5.使用”class-continuation分类” 隐藏实现细节
5.使用”class-continuation分类” 隐藏实现细节
通过”class-continuation 分类”向类中新增实例变量 如果某属性在主接口申明为”只读”,可以在”class-continuation分类”将其扩展为”可读写” 把私有方法的原型申明在”class-continuation分类”里面 若想使类遵循的协议不为人知,则可于”class-continuation分类”中声明
6.通过协议提供匿名对象(??)
6.通过协议提供匿名对象(??)
协议可在某种程度上提供匿名类型。具体的对象类型可以淡化成遵从某协议的ID类型,协议里规定了对象所应实现的方法 使用匿名对象来隐藏类型名称(或类名) 如果具体类型不重要,重要的对象能够响应(定义在协议里的)特定方法,那么可以使用匿名对象来表示
推荐阅读
-
《Effective C++》读书笔记 资源管理
-
《Effective C++》读书笔记 被你忽略的关于构造析构赋值
-
Effective Object-c 2.0 读书笔记
-
Effective C++ 读书笔记 Item26 为什么要推迟变量的定义?
-
《Effective C++》读书笔记
-
Effective Modern C++读书笔记:auto(条款5-6)
-
读书笔记《Effective C++》条款21:必须返回对象时,别妄想返回其reference
-
读书笔记《Effective c++》 条款21 必须返回对象时,别妄想返回其reference
-
iOS之《Effective Objective-C 2.0》读书笔记(10)
-
Effective C++ 第7章读书笔记(总结)