学习笔记-NSPointerArray

5,275 阅读2分钟

今日金句:好记心不如烂笔头

看过的知识点,过段时间,不用或者不看,太容易忘记了,为了督促自己,也为了以后的巩固,看到的知识点在这里记录一下。

NSPointerArray

A collection similar to an array, but with a broader range of available memory semantics.

一个类似于数组的集合,但是具有更广泛的内存语义。

文档介绍截图

大概就是介绍了NSPointerArray的如下几个特点:

  • NSPointerArray可以存放nil
  • 可以插入删除nil
  • count 属性可以设置 (用nil占位)
  • 可以初始化以保持对对象的强引用或弱引用,也可以根据NSPointerFunctionsOptions定义的任何内存或个性选项进行初始化
  • NSCopying和NSCoding协议仅在指针数组初始化为保持对对象的强引用或弱引用时才适用
  • 遵循 NSFastEnumeration,可以通过 for...in 来进行遍历

验证用nil占位

 NSPointerFunctions *funcions = [NSPointerFunctions pointerFunctionsWithOptions:NSPointerFunctionsStrongMemory];
NSPointerArray *pointerArray1 = [[NSPointerArray alloc] initWithPointerFunctions:funcions];
    for (int i = 0; i < 8; i++) {
        CALayer *layer = [CALayer layer];
        layer.backgroundColor = [UIColor clearColor].CGColor;
        [pointerArray1 addPointer:(__bridge void * _Nullable)(layer)];
    }
    pointerArray1.count = 10;
    [pointerArray1 addPointer:nil];
    
    for (id item in pointerArray1) {
        NSLog(@"%@",item);
    }
    NSLog(@"%@",[pointerArray1 allObjects]);
    NSLog(@"%lu",(unsigned long)pointerArray1.count);

根据打印结果可知:

  • allObjects 是没有值为nil的元素的
  • 通过for...in 可以把包含nil的元素遍历出来

打印结果

NSPointerArray的应用

其实也是我写这篇文章的起因~

是在看SDWebImage源码的时候注意到有对NSPointerArray的使用

// element is weak because operation instance is retained by SDWebImageManager's runningOperations property
// we should use lock to keep thread-safe because these method may not be acessed from main queue
- (NSPointerArray *)sd_animationOperationArray {
    @synchronized(self) {
        NSPointerArray *operationsArray = objc_getAssociatedObject(self, &animationLoadOperationKey);
        if (operationsArray) {
            return operationsArray;
        }
        operationsArray = [NSPointerArray weakObjectsPointerArray];
        objc_setAssociatedObject(self, &animationLoadOperationKey, operationsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        return operationsArray;
    }
}

- (void)sd_cancelCurrentAnimationImagesLoad {
    NSPointerArray *operationsArray = [self sd_animationOperationArray];
    if (operationsArray) {
        @synchronized (self) {
            for (id operation in operationsArray) {
                if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
                    [operation cancel];
                }
            }
            operationsArray.count = 0;
        }
    }
}

除此之外,我们用到的其他三方库中还有FSCalendar中也用到了NSPointerArray

self.eventLayers = [NSPointerArray weakObjectsPointerArray];
        for (int i = 0; i < 3; i++) {
            CALayer *layer = [CALayer layer];
            layer.backgroundColor = [UIColor clearColor].CGColor;
            [self.contentView.layer addSublayer:layer];
            [self.eventLayers addPointer:(__bridge void * _Nullable)(layer)];
        }

暂时还没看到有使用其他内存语义(NSPointerFunctionsOptions)的使用,NSPointerFunctionsWeakMemory适用于ARC或GC,会在最后一次释放之后置为null.

根据SDWebImage中这句注释element is weak because operation instance is retained by SDWebImageManager's runningOperations property,也可以更好的理解NSPointerFunctionsOptions所起到的作用,以及和NSArray的区别

  • 保持被添加对象的强引用或者弱引用