iOS开发Tip之二

iOS开发Tip之二

  1. 如何给NSArray添加弱引用对象

    使用NSValue做一个包装,再添加到NSArray

    1
    NSValue * weakValue = [NSValue valueWithNonretainedObject:[NSObject new]];
  2. 将main.m 展开为C代码

    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp

  3. 在子线程里面开启runloop的话,必须要添加autoreleasepool,不然会引发内存泄漏

    每个子线程在开始的地方会有一个autoreleasepool,结束的时候清空pool,但是因为runloop导致线程无法结束,所以如果不手动添加pool,那么必然会内存泄漏

  4. 给一个可变对象的@property使用copy修饰,必须override这个属性,并用mutableCopy代替copy

  5. 如何调试EXC_BAD_ACCESS错误

    一般情况下是因为访问了已经被释放的对象造成的。这种对象称之为僵尸对象(Zombie Objects)。

    我们可以打开Scheme->Diagnostics中的Enable Zombie Objects选项。这样程序运行过程中所有引用计数为0的对象都不会被销毁,当对僵尸对象发送消息的时候就会触发错误,并在控制台中打印出相应的错误。

    以下是模拟僵尸对象的代码

    1
    2
    3
    4
    5
    NSString * str = [NSString stringWithCString:"hello world" encoding:NSUTF8StringEncoding];
    __unsafe_unretained NSString * zombie = str;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [zombie uppercaseString];
    });

    打开Enable Zombie Objects选项之后终端输出为:

    1
    2
    objc[57939]: Class _NSZombie_OS_xpc_endpoint is implemented in both ?? (0x60c0000495d0) and ?? (0x60c0000497e0). One of the two will be used. Which one is undefined.
    2018-08-08 23:08:21.682727+0800 demo1[57939:39012491] *** -[CFString uppercaseString]: message sent to deallocated instance 0x60c00003b3a0
  6. 用@property写一个单例,逼格更高

    1
    @property (nonatomic, class, readonly, nonnull) SDImageCachesManager *sharedManager;

    实现和平常一样

    1
    2
    3
    4
    5
    6
    7
    8
    + (SDImageCachesManager *)sharedManager {
    static dispatch_once_t onceToken;
    static SDImageCachesManager *manager;
    dispatch_once(&onceToken, ^{
    manager = [[SDImageCachesManager alloc] init];
    });
    return manager;
    }

    用法

    1
    [SDImageCachesManager.sharedManager addCache:newCache];
  7. 绝对禁止给Category覆盖父类方法

    因为Category中的方法无法调用父类方法,所以会造成不可预料的覆盖。理论上Category只能新增方法。