## 1. OC 的起源

OC 的方法(本质上讲是消息)在运行时决定。使用函数调用的语言,由编译器决定。如果涉及多态,则用到虚函数表。

## 2. 少在头文件中引用其他文件

1. 两个头文件互相引用会导致编译错误

2. 引用协议,超类时,无法使用前向声明(`@class`),只能引用头文件

3. 协议一般放在单独的文件中,委托协议除外

## 3. 多用字面量语法

1. 向数组中插入 `nil` 时,如果使用字面量会直接报错,如果是使用初始化方法,则 `nil` 以后的对象被忽略

2. 字典也是同理

## 4. 多用常量,少用 #define

1. 不在头文件里面声明预处理命令,防止被别的文件引用,`static const` 也不能用

2. 在 `.m` 文件里面声明的变量,需要加上 static,不然会产生外部符号,重复的外部符号会导致编译错误

3. 用 `static const` 定义只在类内部可见的常量

4. 用 `extern` 定义全局常量,并使用类名作为前缀

5. 头文件中使用 `static const` 会在每个编译单元中出现一个字符串对象,而用 `extern` 定义的对象放在全局符号表中。参考链接:[static const Vs extern const](http://stackoverflow.com/questions/23652665/static-const-vs-extern-const)

6. 使用 `FOUNDATION_EXPORT` 比 `extern` 更好,参考链接:[“FOUNDATION_EXPORT” vs “extern”](http://stackoverflow.com/questions/10953221/foundation-export-vs-extern)

## 5. 用枚举表示状态和选项

1. 按位或操作来组合的枚举使用 `NS_OPTIONS` 宏定义,不需要相互组合的用 `NS_ENUM ` 来定义。

2. 尽可能指定枚举变量的类型

# 对象、消息、运行期

## 6. 理解“属性”这一概念

1. 如果直接使用实例变量,系统会根据偏移量来确定它们的位置。如果后来新增了实例变量,会导致重新编译。

2. `@property` 的作用是合成存取方法

3. `@synthesize` 的作用是指定实例变量的名字,目前默认会执行 `@synthesize xxx = _xxx;`

4. `@dynamic` 的作用是不要创建实例变量,也不要创建存取方法

## 7. 在对象内部尽量直接访问实例变量

1. 直接访问实例变量不会经过方法派发,不会触发内存管理语义,不会触发 KVO,无法调试(加断点)。

2. 可以考虑通过直接读取实例变量来加快读取速度

3. 初始化方法中不要调用 setter,这是因为子类有可能重写设置方法。参见 Demo 的 `EOCSmithPerson.m` 文件。

4. 如果属性是惰性初始化的,必须通过 getter 来读取。

## 8. 理解对象等同性

1. 应该保证相等的对象具有相等的 `hash` 值,但即使 `hash` 值不同,也不影响判断对象等同性。但是考虑到对象加入集合中的情况,我们总是应该为相同的对象提供相同的哈希值。

2. 要么确保对象的哈希值不依赖内部可变的状态,要么确保依赖的状态不会改变。

## 9. 以“类族模式”隐藏实现细节

1. 用类族模式可以将实现细节隐藏,返回基类的对象,并且通过多态完成任务。这其实是一种工厂模式。

2. 注意此时调用 `isMemberOf: superClass` 的返回结果是 `NO`,因为对象实际上是子类的实例。调用 `isKindOf: superClass` 的返回结果则是 `YES`。

3. `[arrayInstance class] = [NSArray class]` 的返回结果总是 `NO`,因为左边一定是 `NSArray` 的子类。

## 10. 使用关联对象

1. 使用静态全局变量作为键,设置好合适的内存管理语义

## 11. objc_msgSend

1. 大部分消息调用使用了 `objc_msgSend` 函数。对于某些边界情况,运行时环境可能使用一些其他的函数来处理:`objc_msgSend_stret`:如果返回的是结构体,调用这个函数。`objc_msgSend_fpret`:如果返回的是浮点数,调用这个函数。`objc_msgSendSuper`:如果给超类发消息,调用这个函数。

## 12. 消息转发

1. 分为三个步骤,动态方法解析,快速转发和完整转发

2. 实现一个“字典”对象:TBD

## 14. 理解“类对象”

1. 运行期检视对象类型被称为“内省”

2. 因为类对象是单例,所以可以直接通过 `==` 判断类对象是否相等。但应该避免这么做,推荐使用类型信息查询方法(`isMemberOf` 和 `isKindOf`)。TBD:举例说明

# 接口与 API 设计

## 15. 用前缀避免命名空间冲突

1. 前缀至少是三个字母,两个字母的前缀由 Apple 保留

2. 全局函数和变量需要注意避免冲突

3. 在自己开发的库中,为用到的第三方库添加前缀

## 16. 全能初始化方法

1. 设置一个全能初始化方法,别的初始化方法都调用它

## 17. 实现 description 方法

1. 实现 `description` 方法,改变 `NSLog` 时的输出结果

2. 实现 `debugDescription` 方法,改变 `po` 时的输出结果

## 18. 尽量使用不可变对象

1. 不要把可变的 collection 作为属性公开,应该公开一个不可变的 collection 然后提供相关的修改方法

## 19. 命名方式

1. 如果返回值是新建的,首个词是返回值类型

2. 不要使用 `str` 这种简称,使用 `string`

3. `get` 前缀仅在由“输出参数”保存返回值的方法中使用

## 21. 错误类型

1. 严重的错误可以直接抛出异常(比如禁止调用父类的方法,需要子类重写)

2. 一般的错误使用 `NSError`,指定 domain(全局常量)、错误码(枚举类型)和用户细信息。

## 22. NSCopying 协议

1. 实现 `NSCopying` 协议,重写 `copyWithZone` 方法。

2. 容器的拷贝总是浅拷贝,`copy` 与 `mutableCopy` 的区别只是返回对象是否可变。

# 协议与分类

## 23. 使用委托

1. 调用 delegate 中的方法时,总是应该传入发起委托的对象。这样代理对象可以判断不同的委托者。

## 24. 使用分类

1. 可以把所有的私有方法都归入名叫 Private 的分类中

## 25. 为第三方分类添加前缀

1. 分类中定义的方法可以多次互相覆盖,以最后一个分类为准

2. 向第三方类中添加分类时,为分类名称和方法名称添加前缀

## 26. 分类中不要声明属性

1. 分类中无法创建实例变量

2. 可以定义存取方法,但是不要定义属性

熟悉 Objective-C的更多相关文章

  1. 第一章 熟悉Objective -C 编写高质量iOS与OS X代码的52 个有效方法

    第一章 熟悉Objective -C   编写高质量iOS与OS  X代码的52 个有效方法   第一条: 了解Objective-C 语言的起源 关键区别在于 :使用消息结构的语言,其运行时所应执行 ...

  2. 熟悉Objective—C

    1.oc使用消息结构而非函数调用 使用消息结构的语言,运行时所应执行的代码由运行环境来决定,而是用函数调用的语言,则由编译器决定.函数调用:如果调用的函数是多态的,那么在运行时就要按照“虚方法表”来查 ...

  3. Effective Objective-C 的读书笔记

    本文主要是摘录了 <Effective Objective-C 2.0>一书中提到的编写高质量iOS 代码的几个方法. 1 熟悉Objective -C 1.1 OC 起源 OC 为C语言 ...

  4. Automake

    Automake是用来根据Makefile.am生成Makefile.in的工具 标准Makefile目标 'make all' Build programs, libraries, document ...

  5. 刨根问底Objective-C Runtime

    http://chun.tips/blog/2014/11/05/bao-gen-wen-di-objective%5Bnil%5Dc-runtime-(2)%5Bnil%5D-object-and- ...

  6. Windows下搭建objective C开发环境

    摘自:http://blog.csdn.net/zhanghefu/article/details/18320827 最近打算针对iPhone.iPod touch和iPad开发一些应用,所以,需要开 ...

  7. Windows在结构objective C开发环境

    对于近期打算iPhone.iPod touch和iPad开发一些应用程序,所以.需要开始学习Objective C(苹果推出的类似C语言的开发语言).因为苹果的自我封闭的产业链发展模式(从芯片.机器. ...

  8. 刨根问底Objective-C Runtime(4)- 成员变量与属性

    http://chun.tips/blog/2014/11/08/bao-gen-wen-di-objective[nil]c-runtime(4)[nil]-cheng-yuan-bian-lian ...

  9. 高薪诚聘熟悉ABP框架的.NET高级开发工程师(2016年7月28日重发)

    招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司-上海运图贸易有限公司 招聘岗位:.NET高级开发工程师工作地点:上海-普陀区 [公司情况]上海运图贸易有限公司,是由易迅网的创始 ...

  10. 学习Spring——两个你熟悉的不能再熟悉的场景使用

    最近公众号受邀获取了留言和赠送模板的权限,小开心(欢迎去公众号JackieZheng围观). 我们大致的了解了Spring这个框架对于依赖注入的使用和诠释可谓是淋漓尽致.因为有了Spring的这个IO ...

随机推荐

  1. 夺命雷公狗—angularjs—17—angularjs的静态库

    在实际的开发中我们往往已经离不开我们的静态库了,因为那里面有太多强悍的功能了,比如路由都是通过一个angular-route的库来实现的,, 那个库,我们可以在百度静态资源公共库来查找,查找方法如下所 ...

  2. [php笔记]项目开发五个阶段/雇员管理系统

    zend 公司,管理PHP版本的升级. 功能强大, 官方推荐. (开发一个PHP项目) 软件开发的五个阶段. 1.创建一个项目(工程)2.设置该项目的路径3.创建一个文件test.php ***使用Z ...

  3. sql server中index的REBUILD和REORGANIZE

    参考文献: http://technet.microsoft.com/en-us/library/ms188388.aspx 正文 本文主要讲解如何使用alter index来rebuild和reor ...

  4. 嵌套错误Inline markup blocks (@<p>Content</p>) cannot be nested. Only one level of inline markup is allowed

    例子: @{Html.Telerik().Splitter().Name("MainSplitter") .Orientation(SplitterOrientation.Vert ...

  5. 161123、ssh scp 复制文件和文件夹

    复制文件或目录命令:  复制文件:  (1)将本地文件拷贝到远程  scp 文件名用户名@计算机IP或者计算机名称:远程路径 本地192.168.80.100客户端  scp /root/instal ...

  6. Akka.NET

    https://github.com/akkadotnet Akka是什么? 可扩展的分布式实时事务处理 编写正确的并发,容错和可扩展的应用程序是太难了.大多数时候,这是因为我们使用了错误的工具和错误 ...

  7. 为博客启用MetaWeBlog API

    最近想写一个博客系统,主要有以下几点功能. 能够使用Live Writer来发布.修改文章 使用MongoDB作为持久化 对于博客中的图片.CSS.JS文件,使用CDN加速 后期可加上Radis 使用 ...

  8. Linux下查看用户列表

    cat /etc/passwd 可以查看所有用户的列表 w 可以查看当前活跃的用户列表 cat /etc/group 查看用户组

  9. JavaScript,base64加密解密

    直接下载吧: http://files.cnblogs.com/files/xiluhua/base64Decode.js

  10. MySQL存储引擎中的MyISAM和InnoDB区别详解

    在使用MySQL的过程中对MyISAM和InnoDB这两个概念存在了些疑问,到底两者引擎有何分别一直是存在我心中的疑问.为了解开这个谜题,搜寻了网络,找到了如下信息: MyISAM是MySQL的默认数 ...