Effective Objective-C 2.0 阅读笔记 二

版权声明:欢迎指出错误,作者极懒,常常懒得修改 https://blog.csdn.net/KevinAshen/article/details/86507291

参考文章

字面数值

    //使用方法来创建显得繁琐复杂
    NSNumber *someNumber = [NSNumber numberWithInt:1];
    //上下两句结果完全一致的同时这样写明显简单多了
    NSNumber *someNumber = @1;
    
    //而且根据不同的字面值直接能创建不同类型的,不用换方法
    NSNumber *floatNumber = @2.5f;
    NSNumber *boolNumber = @YES;

字面量数组

    //一样简单方便
    NSArray *animals = @[@"cat", @"dog"];
    
    //这样写还有一大好处就是如果数组元素里有nil,使用字面量创建会直接报错,方法创建却不会,会直接断开。
    //也就是说使用字面量数组可以避免数组元素出错(因为会直接报错)
    
    //另外在查找某下标的元素时也可以像C语言那样直接
    NSString *dog = animals[1];

字面量字典

    //创建字典使用字面量简单易懂,也有出现nil报错的特性
    NSDictionary *personData = @{@"firstName" : @"Matt", @"age" : @28};
    
    //同样按照特定键来查找元素也方便多了
    NSString *lastName = personData[@"lastName"];

可变数组与字典

    //修改方便
    mutableArray = @"dog";
    mutableDictionary[@"lastName"] = @"Galloway";

使用字面量的局限性

  • 使用字面量创建的都是不可变的
  • 如果想要可变数组需要NSMutableArray *mutable = [@[@1, @2, @3, @4] mutableCopy];

多用类型常量

  • 使用#define无法说明数据的类型,只是简单的代码替换,在大型合作时会显得疲惫
  • 定义常量格式:static const 类型 名称 =
  • 命名习惯:
    • 在单独文件内可见:前面加k
    • 在类之外可见:以类名做前缀
  • 在实现文件内使用的常量还是直接写在.m文件里#import下面
  • const代表常量不可变,一旦修改会报错
  • static代表该变量只会在定义次变量的编译单元中可见
  • 事实上这样写本质上和#define已经没有什么区别了,依然直接是代码替换
  • 如果希望实现的是对外公开即放在“全局符号表”,我们需要这么写
    //in the header file
    extern NSString *const EOCStringConstant;
    
    //in the implementation file
    NSString *const EOCStringConstant = @"VALUE";
    
    //记住要以类名为前缀

用枚举表示状态, 选项, 状态

  • 枚举值多是用在状态码,选项和状态码值
  • 下面是iOS自带枚举类型,使用了NS_ENUM, NS_OPTIONS两种宏
//不需要使用按位操作或操作组合的枚举使用NS_ENUM
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
    UIViewAnimationTransitionNone,
    UIViewAnimationTransitionFlipFromLeft,
    UIViewAnimationTransitionFlipFromRight,
    UIViewAnimationTransitionCurlUp,
    UIViewAnimationTransitionCurlDown,
};

//需要使用按位操作或操作组合的枚举使用NS_OPTIONS
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
    UIViewAutoresizingNone                 = 0,
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
  • 枚举值用二进制表示, 在使用位操作后会有独一无二的值, 从而可以判断是否启用
  • 在switch语句里使用枚举注意不要default

理解“属性概念”这一概念

  • 属性特质
    • 原子性
      • 一般只使用nonatomic
      • 想了解具体可以看第一篇参考文章
    • 读/写权限
      • readwrite
        • 生成getter与setter方法
      • readonly
        • 只有getter方法, 只有用@synthesize才能指定setter方法
        • 可以公开设置成readonly, 在class-continuation分类里定义为readwrite
    • 内存管理语义
      • 影响setter方法的特性
      • 一共五种
        • assign:对“纯量类型”简单赋值
        • strong:保留新值,释放旧值,设置新值
        • weak:同assign,只是可以设定的对象广
        • unsafe_unretained:同weak,只是摧毁时不会自动清空属性
        • copy:同strong,主要在于可以拷贝
      • 这本书讲的好像不是很好,还是推荐看这个iOS关于属性关键字,你又知道多少?
    • 方法名
      • 可以加入getter/setter = 指定setter/getter方法名

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

  • 用不用点语法差别很大
    • 比如我有一个name属性
    • self.name我们叫点语法访问,而_name这样叫做直接访问
    • 直接访问比较快,不经过“方法派发”环节
    • 直接访问直接跳过内存管理语义(assign等)
    • 直接访问不会触发KVO
    • 点语法访问可以在setter/getter处设置断点检验错误
  • 因此推荐是读取直接读取, 写入通过属性, 初始化与dealloc用直接
  • 惰性初始化
    -(NSMutableArray *)cards
    {
        if(!_cards)
            _cards = [[NSMutableArray alloc]init];
        return _cards;
    }
  • 这一条实在有些看不懂

理解“对象等同性”这一概念

  • ==比较的是两个指针, 而isEqual比较的是对象本身
  • 自己写一个判断等同性的方法
    //这个方法就是比较每一个属性, 如果都是相等的就返回YES
    - (BOOL)isEqualToPerson:(EOCPerson *)otherPerson {
        if (self == object) return YES;
        
        if (![_firstName isEqualToString : otherPerson.firstName])
            return NO;
        if (![_lastName isEqualToString : otherPerson.lastName])
            return NO;
        if (_age != otherPerson.age)
            return NO;
        return YES;
    }
    
    //重写isEqual方法, 如果属于同一个类就使用自己的方法, 不然就交给超类判断
    - (BOOL)isEqual : (id)object {
        if ([self class] == [object class]) {
            return [self isEqualToPerson:(EOCPerson *)object];
        } else {
            return [super isEqual : object];
        }
    }
  • super关键字:self和super都是指向当前实例的,不同的是,[self class]会在当前类的方法列表中去找class这个方法,[super class]会直接开始在当前类的父类中去找calss这个方法,两者在找不到的时候,都会继续向祖先类查询class方法,最终到NSObject类。
  • 对于唯一的实例,我们可以仅仅比较一个主键来判断是否相等

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

  • 简单来说就是使用基类, 结合枚举, 将大量的重复的细节放在基类去实现
  • OC没办法标明抽象类,一般抽象类没有初始化方法

猜你喜欢

转载自blog.csdn.net/KevinAshen/article/details/86507291