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

 

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

关键区别在于 :使用消息结构的语言,其运行时所应执行的代码由运行环境来决定。而使用函数调用的语言,则由编译器决定。如果范例代码中调用的函数是多态的,那么在运行时就要按照虚方法表 virtual table 来查出到底应该执行那个函数实现。而采用消息结构的语言,不论是否多态,总是在运行时才会去查找所要执行的方法。

实际上,编译器甚至不关心接受消息的对象是何种类型。接受消息的对象问题也要在运行时处理,其过程叫做动态绑定 dynamic binding .

 

 

Objective -C 语言中的指针是用来指示对象的。

对象所占内存总是分配在堆空间 heap space 中,而绝不会分配在栈stack 上。不能在栈中分配对象。

 

NSString *someString =@"The string";

someString 变量指向分配在堆里的某块内存,其中含有一个NSString 对象。也就是说,如果再创建一个变量,令其窒息那个同一地址,那么并不拷贝该对象,指示这两个变量同时指向此对象。

 

NSString *someString =@"The string";

NSString *anotherString=someString;

 

两个变量都是NSString* 型。这说明当前 stack frame 栈 帧里分配了两块内存,每块内存的大小都能容下一枚指针。

这两块内存的值都一样,就是NSString实例的内存地址。

分配在堆中的内存必须直接管理,而分配在栈上用于保存变量的内存则会在其栈帧弹出时自动清理。

 

Objective -C 将堆内存管理抽象出来了。不需要用malloc 以及free来分配或释放对象所占内存。Objective-C运行期环境把这部分工作抽象出来为一套内存管理架构。叫做引用计数 reference couting .

在Objective -C 中,有时会遇到定义里不含* 的变量,他们可能会使用栈空间 stack space .这些变量所保存的不是Objective-C 对象。

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

 

第三条: 多用字面量语法,少用与之等价的方法

字符串字面量 string literal 其语法是

NSString * someString =@"HAHA";

使用字面量语法literal syntax 可以缩减源代码长度,使其更为易读。

字面数值 有时需要把整数、浮点数 、布尔值封入OC 对象中,这种情况下可以用NSNumber类。

NSNumber *someNumber=[NSNumber numberWithInt :1];

可以这样写

NSNumber *someNumber=@1;

 

第四条:多用类型常量 ,少用#define 预处理指令

编写代码时经常要定义常量 。

#define ANIMATION_DURATION 0.3 

定义出来的常量没有类型信息。 

要想解决此问题,应该设法利用编译器的某些特点才对。有个办法比用预处理指令来定义常量更好。

static const NSTimeInterval kAnimationDuration =0.3;

请注意,用此方法定义常量包含类型信息,其好处是清楚的描述了常量的含义。

如果要定义许多常量,那么这种方式能令阅读代码的人更易理解其意图。

常用的命名法是:若常量局限于某编译单元 translation unit 也就是实现文件 implementation file 之内,则在前面加字母k。若常量在类之外可见,则通常以类名为前缀。

 

定义常量的位置很重要。 我们总喜欢在头文件里声明预处理指令,这样做不好。当常量名称有可能冲突时更是如此。例如 ,ANIMATION_DURATION 这个常量的名字就不该出现在头文件中,因为所有引入了这份头文件的其他文件都会出现这个名字,其实就连static const 定义的常量也不应该出现在头文件中。因为OC 中没有命名空间 namespace 这一概念。所以那样做都等于声明了一个名叫kAnimationDuration 的全局变量。此名称应该加上前缀,以表明其所属的类,例如可改为EOCViewClassAnimationDuration .

若不打算公开某个常量,则应将其定义在使用该变量的实现文件中。

变量一定要同时用static 与const  来声明。如果试图修改由const 修饰符所声明的变量,那么编译器就会报错。而 static 修饰符则意味着该变量仅在定义此变量的编译单元中可见

编译器每收到一个编译单元,就会输出一份目标文件。在OC的语境下,编译单元一次通常指每个类的实现文件(以.m为后缀名)。因此,在上述范例代码中声明的kAnimationDuration变量,其作用域仅限于由EOCAnimatedView.m 所生成的目标文件中。

假如声明此变量时不加static ,则编译器会为它创建一个外部符号external symbol .此时,若是另一个编译单元也声明了同名比阿娘,那么编译器就会抛出一条错误消息:

 

实际上,如果一个变量声明为Static,又声明为const ,那么编译器根本不会创建符合,而是会像#define 预处理指令一样,把素有遇到的变量都替换为常值。

 

有时候需要被外部使用,此类变量需放在全局符号表 global symbol table 中,以便可以在定义该常量的编译单元之外使用。因此,其定义方式与static const 有所不同。应该是这样定义: 

 

 

常量定义从右至左解读,所以在本例中,EOCStringConstant 就是一个常量,而这个常量是指针,指向NSString 对象。

第五条:用枚举表示状态、选项、状态码 

新版系统框架中使用了 强类型 strong type 的枚举。

枚举只是一种常量命名方式。某个对象所经历的各种状态可以定义为一个简答的枚举 enumeration set .

由于每种状态都用一个便于理解的值来表示,这样写出来的代码更容易理解。

 

最新文章

  1. .NET 创建Windows服务,及服务的安装卸载
  2. apache中若干模块的安装
  3. java web 文件上传下载
  4. 使用JAVA客户端对HDFS进行代码编写(五)
  5. 完全用 GNU/Linux 工作(转)
  6. shell编程笔记(基本部分)
  7. angular 如何获取使用filter过滤后的ng-repeat的数据长度
  8. UniRX简述
  9. mqtt mosquitto 源码安装
  10. ios 在使用 SDWebimage UIButton setBackgroundimage
  11. ios 回调函数作用
  12. es数组去重的简写
  13. Bugfree——CentOS6.8搭建测试环境
  14. Java虚拟机(JVM)你只要看这一篇就够了!
  15. 关于ueditor与arcgis js api同用会报错的问题
  16. Redux学习之解读applyMiddleware源码深入middleware工作机制
  17. Spring的事物传播行为
  18. Spring不支持静态注入
  19. 如何在qt中使用中文输入法
  20. Java的==与equals之辨

热门文章

  1. Pycharm中如何安装python库
  2. 书写优雅的shell脚本(一)- if语句
  3. iOS成员变量、实例变量、属性变量三者的联系与区别
  4. HNOI2008 GT考试 (KMP + 矩阵乘法)
  5. @font-face 用fontsquirrel把ttf文件获取别的文件格式
  6. Ruby 类的创建
  7. Moctf--unset
  8. Codeforces645B【树状数组求逆序数】
  9. gcc降版本方法 - [学习]
  10. ubuntu 18 安装virtulenv以及virtualenvwrapper