读SDWebImage 心得体会

信号量的使用(宏定义)

// - 先定义两个宏
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);

// - 初始化一个信号量
dispatch_semaphore_t weakCacheLock = dispatch_semaphore_create(1);
self.weakCacheLock = weakCacheLock;

// - 使用宏定义的信号量
LOCK(self.weakCacheLock);
 NSLog(@"需要线程安全的操作 写在这个位置")
UNLOCK(self.weakCacheLock);

在宏定义中使用bloc

// - 1. 先定义一个宏定义
#define DYTestBlock(param1, block)\
NSLog(@"param1 : %@", (param1));\
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(9 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\
    int blockParam1 = 1;\
NSString *blockParam2 = [NSString stringWithFormat:@"哈哈 : %@", param1];\
    block(blockParam1, blockParam2);\
});\
// - 2. 调用这个宏定义
    // - 方式1
    void(^block)(int, NSString *) = ^(int a, NSString *str) {
        NSLog(@"%d, %@", a, str);
    };

    DYTestBlock(@"xx",block);

    // - 方式 2
    DYTestBlock(@"xx",^(int a, NSString *str) {
        NSLog(@"%d, %@", a, str);
    });
    // - 方式三
    DYBlock dyBlock ^(int a, NSString *str) {
        NSLog(@"%d, %@", a, str);
    };

    DYTestBlock(@"xx",dyBlock);

耗时操作的处理(任何耗时:包括IO读写、转码等操作,都不应该放到主线程里面使用。)

// - 先定义一个队列
 dispatch_queue_t ioQueue = dispatch_queue_create("com.hackemist.SDWebImageCache", DISPATCH_QUEUE_SERIAL);
 self.ioQueue = ioQueue;

// - 在工作线程处理 并同步返回结果
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key {
    if (!key) {
        return NO;
    }
    __block BOOL exists = NO;
    dispatch_sync(self.ioQueue, ^{
        exists = [self _diskImageDataExistsWithKey:key];
    });

    return exists;
}

 // - 在工作线程处理 并在主线程回调
 dispatch_async(self.ioQueue, ^{
            [self.fileManager removeItemAtPath:[self defaultCachePathForKey:key] error:nil];

            if (completion) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    completion();
                });
            }
        });

申请后台任务

这里有个疑问点要注意,为啥会存在前后两部分都去释放Task任务。
iOS的后台任务有个背景,不管任何时候,都需要手动去调用endBackgroundTask结束后台任务,其实开启一个后台job的时候,因为时长有限,所以会存在两种结局:
1. 在允许的时间内执行完成
2. 规定时间内未执行完成
如上两种情况,在结束后都必须手动调用endBackgroundTask:;

// - 添加通知的监听
[[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(backgroundDeleteOldFiles)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];

// - 执行后台任务
- (void)backgroundDeleteOldFiles {
    Class UIApplicationClass = NSClassFromString(@"UIApplication");
    if(!UIApplicationClass || ![UIApplicationClass respondsToSelector:@selector(sharedApplication)]) {
        return;
    }
    UIApplication *application = [UIApplication performSelector:@selector(sharedApplication)];
    __block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    [self deleteOldFilesWithCompletionBlock:^{
        [application endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
}

声明一个废弃的方法和声明一个建议的初始化方法

// - __deprecated_msg(用于提示此方法或属性已经废弃。)
@property (nonatomic, assign) BOOL shouldUseCredentialStorage __deprecated_msg("Property deprecated. Does nothing. Kept only for backwards compatibility");

// - NS_DESIGNATED_INITIALIZER(用于告诉调用者要用这个方法去初始化类对象)
- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration NS_DESIGNATED_INITIALIZER;

猜你喜欢

转载自blog.csdn.net/qq_27074387/article/details/79862769