美文网首页
观“编写高质量iOS与OC 代码的52个有效方法”有感(一)·

观“编写高质量iOS与OC 代码的52个有效方法”有感(一)·

作者: 大王叫我来巡山_Cong | 来源:发表于2016-12-05 17:49 被阅读420次
程序猿.jpg

1、了解Objective-C语言的起源

  • OC语言使用“消息结构” 而非“函数调用”
    消息结构:
    Object *obj = [Object new];
    [obj performWith:parameter1 and:parameter2];
    特点:运行时的代码由运行环境来决定。

函数结构:
Object *obj = new Object;
obj->perform(parameter1,parameter2);
特点:运行时的代码由编译器来决定。

  • OC是C的“超集”,所以C语言的所有功能在编写OC代码时依然适用!
    OC中的内存模型:
    NSString *nameString = @“小伙子”;
    上面就是说:声明了一个名为 nameString 的变量 ,其类型为NSString *
    也就是说,此变量为指向NSString 的指针。当然了不止NSString这样声明,所有Objective-C的对象都必须这样声明。原因:对象所占内存总是分配在“堆空间”中,而不会分配到“栈”上。
  • 在OC中,你还会碰到一些不需要 *的变量。他们可能会使用“栈空间” 这些变量保存的不是Objective-C对象。举个例子
struct CGRect {
    CGPoint origin;
    CGSize size;
};
typedef struct CGRect CGRect;

系统框架都在使用结构体。因为使用Objective-C来做的话会影响性能(创建对象、分配内存、释放内存)。如果只是保存int、float、double、char这些“非对象类型” 通常使用CGRect结构体就可以了。

2、在类的头文件中尽量少引入其他头文件

  • 现象:
    Objective-C创建文件分为.h(头文件)和.m(实现文件)
    假如在某个头文件中引入一些根本用不到的头文件。那么程序也会引入头文件的内容。这样会增加编译时间。
  • 建议:
    除非确实有必要,否则不要引入头文件。
    应该在实现文件中引入要使用的头文件,降低类之间的耦合。

3、多用字面量语法,少用与之等价的方法

  • 实现
    语法创建:
    //多种类型的数值
    NSNumber *number = [NSNumber numberWithInt:1];
    
    //数组创建
    NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
    
    //字典的创建
    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"Mary",@"name",@"Secr",@"name1" ,nil];

字面量创建

//数值创建
    NSNumber *number = @1;
    int a = 1;
    float b = 4.23f;

    //数组创建
    NSArray *array = @[@"1",@"2",@"3"];
    
    //字典的创建
    NSDictionary *dictionary = @{@"Mary":@"name",@"Secr":@"name1"};
  • 结论
    • 使用字面量语法创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要。
    • 用字面量创建数组或者字典时,若值中有nil,则会抛出异常。因此,务必确保值里不含nil。

4、多用类型常量,少用#define预处理指令

  • 编写代码时候经常要定义常量。
    例如一个动画的播放时间
    #define ANIMATION_DURATION 0.3
    预处理指令会把源代码中的ANIMATION_DURATION字符串替换为0.3。
    but、这样定义出来的常量没有类型信息。
    • 名字(duration)这个词看上去与时间有关,但是代码中并没有标出。
    • 假如其他文件中有ANIMATION_DURATION ,也会一律替换成0.3
  • 可以这样解决:
    static const NSTimeInterval kAnimationDuration = 0.3;
    • 包括了类型信息、有助于编写开发文档、让接手代码的人更易读。
    • 试图修改const修改的变量,那么编译器会报错。
  • 注意:
    • 常量的命名规则:
      常量局限于实现文件之内,在前面加字母k。
      若是常量在类之外可见,那么要以类名为前缀。比如SCViewClassAnimationDuration。
  • 外界可见的常值变量:
    • 这种常量放在“全局符号表”中,以便可以在定义该常量的编译单元之外使用!
      .h中
extern NSString *const SCNameStringConstant;

.m中

NSString *const SCNameStringConstant = @"Peter";
  • 原理:
    编译器看到头文件中的extern关键字后,就知道在全局符号表中有一个名叫 SCNameStringConstant 的符号。
    编译器无需查看其定义,允许代码使用此常量。因为它知道肯定能找到这个常量。
  • 注意:
    此常量必须要定义且只能定义一次。通常是定义在与声明常量的头文件相关的实现文件里。链接器会把此目标文件和其他目标文件相链接,形成二进制文件,凡是用到SCNameStringConstant的地方都能解析。
    因为符号要放在全局符号表里,所以命名的时候一定要注意。最好是用与之相关的类名做前缀!

5、用枚举表示状态、选项、状态码

  • 枚举:enum
    系统框架中频繁用到此类型:
    比如创建UIButton时候
typedef NS_ENUM(NSInteger, UIButtonType) {
    UIButtonTypeCustom = 0,                         // no button type
    UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0),  // standard system button

    UIButtonTypeDetailDisclosure,
    UIButtonTypeInfoLight,
    UIButtonTypeInfoDark,
    UIButtonTypeContactAdd,
    
    UIButtonTypeRoundedRect = UIButtonTypeSystem,   // Deprecated, use UIButtonTypeSystem instead
};

枚举只是一种常量命名方式。每种状态用一个易读的值来表示,这样更方便理解。编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1。

  • 比如状态一般分为“OK”和“Error”。只能选择其中一种,不可能出现2种。
    我们可能通过枚举这样做
typedef enum _TTGState {
    TTGStateOK  = 0,
    TTGStateError,
    TTGStateUnknow
} TTGState;

  //指明枚举类型
TTGState state = TTGStateOK;

用的时候就这样:

 - (void)dealWithState:(TTGState)state {
   switch (state) {
       case TTGStateOK:
           //...
           break;
       case TTGStateError:
           //...
           break;
       case TTGStateUnknow:
           //...
           break;
     }
  }
     ```
- 选项:就是说一个“选项变量”的类型要能够同时表示一个或多个组合的选择。
比如说iPhone 可以支持多个方向。

//方向,可同时支持一个或多个方向
typedef enum _TTGDirection {
TTGDirectionNone = 0,
TTGDirectionTop = 1 << 0,
TTGDirectionLeft = 1 << 1,
TTGDirectionRight = 1 << 2,
TTGDirectionBottom = 1 << 3
} TTGDirection;

好处就是我们选项变量可以如下表示:

//用“或”运算同时赋值多个选项
TTGDirection direction = TTGDirectionTop | TTGDirectionLeft | TTGDirectionBottom;

//用“与”运算取出对应位
if (direction & TTGDirectionTop) {
NSLog(@"top");
}
if (direction & TTGDirectionLeft) {
NSLog(@"left");
}
if (direction & TTGDirectionRight) {
NSLog(@"right");
}
if (direction & TTGDirectionBottom) {
NSLog(@"bottom");
}

一般来说,我们不能指定枚举变量的实际类型是什么,就是说,我们不知道枚举最后是int型,还是其他的什么类型。但是从C++ 11开始,我们可以为枚举指定其实际的存储类型。
      enum TTGState : NSInteger {/*...*/};
Foundation框架中定义了一些辅助的宏,这些宏具备了向后兼容的能力(判断编译器是否支持新的枚举特性,不支持就用老的语法来定义枚举)。

- 在iOS程序中,最好所有的枚举都用“NS_ENUM”和“NS_OPTIONS”定义,保证统一。

### 接下来也将会继续整理。如果觉得有用请点个喜欢!
### 您的支持将是我继续写作的动力!谢谢。

[观“编写高质量iOS与OC X代码的52个有效方法”有感(一)· 熟悉Objective-C](http://www.jianshu.com/p/0876e60d3160)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(二)· 对象、消息、运行时](http://www.jianshu.com/p/1aac4fb98888)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(三)· 接口与API设计](http://www.jianshu.com/p/5d9e61db2a01)
[观“编写高质量iOS与OC X代码的52个有效方法”有感(四)· 协议与分类](http://www.jianshu.com/p/0944e1e276ff)

相关文章

网友评论

      本文标题:观“编写高质量iOS与OC 代码的52个有效方法”有感(一)·

      本文链接:https://www.haomeiwen.com/subject/rigkmttx.html