《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中...

注:转载请附上原作者及其链接

第一条:了解Objective-C语言起源

Smalltalk 消息型语言的鼻祖

函数调用语言:由编译器决定
消息结构语言:由运行环境决定
“动态绑定”在运行时才会检查对象类型
“运行期组件”

指针 32位计算机4字节 64位计算机8字节

相比C语言,Objective-C将堆内存管理抽取出来,不需要用malloc和free来分配或释放对象所占内存 — 内存管理架构(引用计数)

例如 CGRect 这种结构体如果改用Objective-C对象来做的话,性能会受影响:创建对象需要额外开销—分配释放堆内存等
结构体分配的内存在栈上,不需要上层管理

第二条:在类的头文件中尽量少引入其他头文件

C C++ OC 头文件+实现文件

这也是编程思想的一种体现,可以说.h和.m文件时完全独立的,只是为了要求有较好的可读性,才要求两个文件的文件名一致,这也是把接口和实现分离,让调用者不必去关心具体的实现细节。

向前声明 @class 告诉编译器某个类存在

《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第1张图片
Snip20170623_4.png

第三条:多用字面量语法(即“语法糖”)

  • 数值
NSNumber *num = [NSNumber numberWithInt:1 ];
// 语法糖形式:
 NSNumber *num = @"1";
  • 数组
NSArray *animals = [NSArray arrayWithObjects:@"cat",@"dog",nil];
// 语法糖形式:
NSArray *animals = @[@"cat",@"dog"];

取元素

NSString *dog = [animals objectAtIndex:1];
// 语法糖形式
NSString *dog = animals[1];

一个小细节:


《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第2张图片
Snip20170623_5.png
  • 字典
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
      @"ma":@"firstName",
      @"yun":@"secondName",
      [NSNumber numberWithInt:28:@"age",
nil]];
// 语法糖形式:
NSDictionary *dict = @{
            @"firstName":@"ma",
            @"secondName":@"yun",
            @"age":@28
};
  • 可变数组和可变字典

取元素替换元素

[mutableArray replaceObjectAtIndex:1 withObject:@"dog"];
[mutableDict setObject:@"hello" forKey:@"lastName"];
// 语法糖
mutableArray[1] = @"dog";
mutableDict[@"lastName"] = @"hello" ;
NSMutableArray *arr = [@[@"1",@"2"] mutableCopy];

第四条:多用常量 ,少用宏

比如把一个动画的播放时长提取出来,如果使用宏有个缺点-没有类型信息

#define ANIMATION_DURATION 0.3;
static const NSTimeinterval kAnimationDuration  = 0.3;

第六条:理解“属性”这一概念(理解@property)

实例变量和@property

@property可以分为四类:

  • 原子性
  • 读写权限
  • 内存管理语义
  • 方法名

第七条:在对象内部尽量直接访问实例变量

第十一条:对象消息 传递 机制

静态绑定:C语言采用的方式
动态绑定: OC采用的方式
选择器(选择子)
消息:选择器+参数

动态消息派发系统:编译器调用objc_msgSend将消息转为标准的C语言函数调用

// 消息机制中的核心函数
objc_msgSend
// 边界情况处理函数
objc_msgSend_stret
objc_msgSend_fpret
objc_msgSendSuper

大致过程:

id returnValue = [someObject messageName:parameter:];
// 编译器转换为如下函数
id returnValue = objct_msgSend(someObject,
                  @selector(messageName:),
                  parameter);
// objct_msgSend会在接收者所属类中的“方法列表”中查找方法实现
// 查找会有缓存 -- 快速映射表
《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第3张图片
Snip20170627_14.png

第十二条:对象消息 转发 机制

对象在收到无法解读的消息之后怎么办?

动态方法解析(所属类能否动态添加方法来处理选择器) --> 看有无“备援接收者” --> 启动完整的消息转发机制

动态方法解析:

+ (BOOL)resolveInstanceMethod:(SEL)selector; // 未实现的方法是示例方法
+ (BOOL)resolveClassMethod:(SEL)selector;// 未实现的方法是类方法

第十四条:理解“类对象”的用意

第三章 接口和API设计

第十五条:用前缀避免命名空间冲突

OC没有命名空间机制,所以我们应该设法避免命名冲突,否则很容易重名,命名冲突会在链接的时候报错

  • 苹果宣称保留两个字母前缀使用的权利,建议使用三个字母(感觉没有啥必要,前缀起名稍微注意一下就可以了);
  • 在将代码发布为程序库的时候尤其要注意给函数等加上前缀,否则很容易造成命名冲突而报“重复符号错误”,代码中用到了其他第三方库也要将第三方库的前缀一并修改统一;

第十六条:提供“全能初始化方法”

《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第4张图片
Snip20170626_13.png

EOCSquare和ECORectangle例子

// 抛出异常
- (id)initWithWidth:(float)width andHeight:(float)height{
  @throw[NSException exceptionWithName: NSInternalInconsistencyException
      reason:@"Must be initWithDimension:instead.",
    userInfo:nil];
}

第十七条:实现description方法

在构建需要打印到日志的字符串的时候,object会收到description消息

  • 把待打印的信息放在字典里
《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第5张图片
Snip20170626_12.png
  • description 和 debugDescription


    《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第6张图片
    Snip20170626_10.png

第十八条:尽量使用不可变对象(即readonly的应用场景)

《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中..._第7张图片
Snip20170626_9.png

第十九条:命名规范

首先OC方法的冗长也是有好处的,可以清晰表达出意图,对比其他语言:

NSString *newText = [text stringByReplacingOCcurrenceOfString:@"fox"
                                                    withString:@"cat"];
// java中
string newText = text.replace("fox","cat");
  • 方法命名
错误示例:
CYRectangle *rectangle = [[CYRectangle alloc] initWithSize:5.0f :10.0f];
正确示例:
CYRectangle *rectangle = [[CYRectangle alloc] initWithWidth:5.0f andHeight:10.0f];

第二十条:为私有方法加前缀

@interface CYObject : NSObject
- (void)publicMethod;
@end 
@implemention CYObject
- (void)publicMethod{
}
// 加前缀
- (void)p_privateMethod{
}
@end

原因:

  • 便于区分公共方法和私有方法;
  • 公共API一般不要轻易改名字,改了可能别的开发者要更新代码,给私有方法加前缀很容易看出哪些方法可以随意改动,哪些方法不可以;

注意:苹果公司喜欢用一个单一的下划线作为私有方法的前缀,所以要求开发者不应该使用作为私有方法的前缀,否则在继承的时候无意的覆盖了父类的方法

第五章:内存管理

第二十九条:理解引用计数
第三十条:以ARC简化引用计数
第三十一条:在dealloc方法中只释放引用并解除监听
第三十二条:编写“异常安全代码”时,留意内存管理问题
第三十三:以弱引用避免保留环
第三十四:以“自动释放块池”降低内存峰值
第三十五:用“僵尸对象”调试内存管理问题
第三十六:不要使用retainCount

你可能感兴趣的:(《Effective Obejctive-C2.0编写高质量iOS和OSX代码的52个有效方法》读书笔记--持续更新中...)