0%

《effective-2.0》 学习笔记

前言

没事要多读书,读好书。

笔记

  1. 类的头文件中尽量少引入其他头文件

    • 使用向前声明(forward declaring)@class 减少编译时间,避免相互引用
    • 非委托协议的协议,单独写一个头文件
  2. 多用类型常量,少用 #define 预处理指令

    • #define 只是简单的替换,不包含类型信息,重新定义时编译器也不会产生警告。

      .m 中如定义个时间常量,比起 #define ANIMATION_DURATION 0.3 可以使用 static const NSTimeInterval kAnimationDuration = 0.3

    • 如果需要对外公开常量

      .hextern NSString * const ConstantString.mNSString * const ConstantString = @"ConstantString";

  3. 理解“块”

    • 全局块、栈块及堆块

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      void (^block)();

      if (condition) {
      block = ^{
      NSLog(@"Block A");
      };
      } else {
      block = ^{
      NSLog(@"Block B");
      };
      }

      block();

      定义在 if 及 else 中的两个块都分配在栈内存中,编译器会给每个块分配好栈内存,然而离开相应范围之后,编译器有可能把分配给块的内存覆写掉。这段代码可以编译但运行时时而正确时而错误。若编译器未覆写待执行的块,则程序照常运行,若覆写,则程序崩溃。

      为解决此问题,可给块对象发送 copy 拷贝,就可以把块从栈复制到堆上。块复制到堆上后就变成带引用计数的对象了。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      void (^block)();
      if (condition) {
      block = [^{
      NSLog(@"Block A");
      } copy];
      } else {
      block = [^{
      NSLog(@"Block B");
      } copy];
      }
      block();

      全局块不会捕捉任何状态,所在全局内存区,在编译期已经完全确定。全局块的拷贝操作是个空操作,因为全局块不可能为系统回收,相当于单例。

      1
      2
      3
      void (^block)() = ^{
      NSLog(@"Block A");
      }