搜集知识iOS DeveloperiOS Swift && Objective-C

重读 Effective Objective-C 2.0 小记

2016-08-30  本文已影响799人  ZeroJ

最近再次拜读了<<Effective Objective-C 2.0>>这本书, 经典的书确实值得阅读, 并且里面的很多东西, 并不过时, 书中有52条建议, 但这里笔者只是选取了其中的几条来分享, 这几条可能是我们在开发中比较常用的, 还有就是因为其他的不是能用很短的语言写出来的, 如果你没有读过这本经典的书, 还是建议阅读一下原书.


  1. 对于OC中的对象声明例如NSObject *obj1 = [NSObject new];, obj1这个指针变量是分配在栈上的, 他指向的是这一个分配在堆上面的实例对象, 如果进行下面的赋值操作NSObject *obj2 = obj1;,那么并没有新生成一个实例对象, 只是在栈上分配了一个新的指针变量obj2, 而obj2和obj1指向的实例对象是同一个.
 NSString *str = @"string";
 NSArray *arr = @[obj1, obj2];
arr[1]// 读取使用下标而尽量不使用对应的函数...
[array setObject:<#(nonnull id)#> atIndexedSubscript:<#(NSUInteger)#>] 
/// 使用static 和const 定义文件内部的常量 一般使用k开头命名
static float const kAnimationTime = 2.0f;
/// 使用const定义全局的常量, 在其他文件中可以通过 extern float const kAnimationTime引入使用, 一般不用k开头命名, 而使用class名字
float const CustomAnimationTime = 2.0f;
    1. 定义一个整形变量, 然后说明, 不同的整数代表不同的状态, 那么这样对于开发就很不方便, 必须得很清楚并且很正确的输入对应的整数才能表示相应的状态, 那么就很容易出错, 和不便于维护
    int statusCode;
    if (statusCode == 200) { }/// 请求成功
    else if () ....
    2. 使用枚举, 对不同的状态定义不同的名字, 这样就很清晰方便了, 当然定义的时候使用NS_ENUM比使用enum要`好`
typedef NS_ENUM(NSInteger, ErrorCode) {
    ErrorCodeNotFind,
    ErrorCodeLostConnection,
    ErrorCodeUnknow
};

显然上面你应该选用枚举, 同时还有一种情况就是, 定义多选项, 这个你是会把他们都放进一个数组中么?? 当然不要这样做, 这个时候也应该使用枚举来定义, 不过会有一点的小技巧, Apple对这种进行了一个包装, 使用NS_OPTIONS而不是enum

typedef NS_OPTIONS(NSInteger, ErrorOptions) {
    ErrorOptionsNone = 0,
    ErrorOptionsOne = 1 << 0, ///左移操作    --- 1 --- 0001
    ErrorOptionsTwo = 1 << 1,               --- 2 --- 0010
    ErrorOptionsThree = 1 << 2              --- 4 --- 0100
};

因为上面定义的枚举值都为2的整数次幂值, 所以后面就可以使用位操作符 与(&)和或(|)来进行选项的筛选

  ErrorOptions options = ErrorOptionsOne | ErrorOptionsTwo; //--- 0011
    if (options & ErrorOptionsOne) {// ErrorOptionsOne
        // 结束判断后面
    }
    else if (options & ErrorOptionsTwo) {// ErrorOptionsTwo
        // ...
    }
    else {
        // ...
    }
      ZJChildClass类里面没有重写initialize方法, 但是他的父类重写了, 所以在初始化ZJChildClass的时候, 父类的initialize会被调用两次, 即会打印两条
    @interface ZJBaseClass : NSObject
    @end
    @implementation ZJBaseClass
    + (void)initialize {
        NSLog(@"加载一次-----");
    }
    @end
    @interface ZJChildClass : ZJBaseClass
    @end

所以一般都是这样来重写initialize方法的, 保证只会像我们期望的那样调用一次

    + (void)initialize {
        if (self == [ZJBaseClass class]) { /// 不能用 [self class]
            NSLog(@"加载一次-----");
       }
    }
 + (instancetype)sharedInstance {
    static Object *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [self new];
    });
    return sharedInstance;
}
上一篇下一篇

猜你喜欢

热点阅读