zoukankan      html  css  js  c++  java
  • 第一章 熟悉Objective -C 编写高质量iOS与OS X代码的52 个有效方法


    第一章 熟悉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 .

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

     

  • 相关阅读:
    元素定位不到的问题,Timeout,nosuch element,unable locate等
    webpack的安装
    Mysql修改表
    Mysq表的创建和l数据类型
    Mysql的库操作
    面向对象的序列化和反序列化
    类的关键字:final、const
    面向对象接口以及和继承的混合案例
    DOM创建移除替换元素
    抽象类
  • 原文地址:https://www.cnblogs.com/ljlkfx/p/4807372.html
Copyright © 2011-2022 走看看