zoukankan      html  css  js  c++  java
  • YYCache 源码分析(一)

    iOS 开发中总会用到各种缓存,YYCache或许是你最好的选择。性能上有优势,用法也很简单。作者ibireme曾经对比过同类轮子:http://blog.ibireme.com/2015/10/26/yycache/

    1.简单架构图

    2.YYCache.h方法分析

    @interface YYCache : NSObject

    // 读取当前数据库名称

    @property (copy, readonly) NSString *name;

    // memoryCache内存缓存,diskCache文件缓存

    @property (strong, readonly) YYMemoryCache *memoryCache;

    @property (strong, readonly) YYDiskCache *diskCache;

    // 可通过下面三种方法来实例化YYCache对象

    - (nullable instancetype)initWithName:(NSString *)name;

    - (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;

    + (nullable instancetype)cacheWithPath:(NSString *)path;

    // 禁止通过下面两个方式实例化对象

    - (instancetype)init UNAVAILABLE_ATTRIBUTE;

    + (instancetype)new __attribute__((unavailable("new方法不可用,请用initWithName:")));

    // 通过key判断是否缓存了某个东西,第二个法是异步执行,异步回调

    - (BOOL)containsObjectForKey:(NSString *)key;

    - (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block;

    // 读--通过key读取缓存,第二个法是异步执行,异步回调

    - (nullable id<NSCoding>)objectForKey:(NSString *)key;

    - (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id<NSCoding> object))block;

    // 增、改--缓存对象(可缓存遵从NSCoding协议的对象),第二个法是异步执行,异步回调

    - (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key;

    - (void)setObject:(nullable id<NSCoding>)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block;

    // 删--删除缓存

    - (void)removeObjectForKey:(NSString *)key;

    - (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block;

    - (void)removeAllObjects;

    - (void)removeAllObjectsWithBlock:(void(^)(void))block;

    - (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress

                                     endBlock:(nullable void(^)(BOOL error))end;

    @end

    3.YYCache使用

    // 0.初始化YYCache

        YYCache *cache = [YYCache cacheWithName:@"mydb"];

        // 1.缓存普通字符

        [cache setObject:@"汉斯哈哈哈" forKey:@"name"];

        NSString *name = (NSString *)[cache objectForKey:@"name"];

        NSLog(@"name: %@", name);

        // 2.缓存模型

        [cache setObject:(id<NSCoding>)model forKey:@"user"];

        // 3.缓存数组

        NSMutableArray *array = @[].mutableCopy;

        for (NSInteger i = 0; i < 10; i ++) {

            [array addObject:model];

        }

        // 异步缓存

        [cache setObject:array forKey:@"user" withBlock:^{

            // 异步回调

            NSLog(@"%@", [NSThread currentThread]);

            NSLog(@"array缓存完成....");

        }];

        // 延时读取

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

            // 异步读取

            [cache objectForKey:@"user" withBlock:^(NSString * _Nonnull key, id<NSCoding>  _Nonnull object) {

                // 异步回调

                NSLog(@"%@", [NSThread currentThread]);

                NSLog(@"%@", object);

            }];

        });

    打印:

    2016-06-09 11:35:44.069 YYCache源码分析[13546:949048] <NSThread: 0x7ffd43f14840>{number = 2, name = (null)}

    2016-06-09 11:35:44.069 YYCache源码分析[13546:949048] array缓存完成....

    2016-06-09 11:35:44.386 YYCache源码分析[13546:949052] <NSThread: 0x7ffd43e01900>{number = 3, name = (null)}

    2016-06-09 11:35:44.386 YYCache源码分析[13546:949052] (

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>",

        "<UserModel: 0x7ffd44014310>"

    )

    // 缓存实现,默认同时进行内存缓存与文件缓存

    - (void)setObject:(id<NSCoding>)object forKey:(NSString *)key {

        [_memoryCache setObject:object forKey:key];

        [_diskCache setObject:object forKey:key];

    }

    // 如果只想内存缓存,可以直接调用`memoryCache`对象

        YYCache *cache2 = [YYCache cacheWithName:@"mydb"];

        [cache2.memoryCache setObject:@24 forKey:@"age"];

        NSLog(@"age缓存在内存:%d", [cache2.memoryCache containsObjectForKey:@"age"]);

        NSLog(@"age缓存在文件:%d", [cache2.diskCache containsObjectForKey:@"age"]);

    打印:

    2016-06-09 21:23:24.326 YYCache源码分析[14512:1085375] age缓存在内存:1

    2016-06-09 21:23:24.326 YYCache源码分析[14512:1085375] age缓存在文件:0

    4.YYCache.h tips

    #if __has_include(<YYCache/YYCache.h>)

    #import <YYCache/YYMemoryCache.h>

    #import <YYCache/YYDiskCache.h>

    #import <YYCache/YYKVStorage.h>

    #elif __has_include(<YYWebImage/YYCache.h>)

    #import <YYWebImage/YYMemoryCache.h>

    #import <YYWebImage/YYDiskCache.h>

    #import <YYWebImage/YYKVStorage.h>

    #else

    #import "YYMemoryCache.h"

    #import "YYDiskCache.h"

    #import "YYKVStorage.h"

    #endif

    __has_include:用来检查Frameworks是否引入某个类,

    像YYWebImage已经集成YYCache,如果导入过YYWebImage则无需重新导入YYCache

    NS_ASSUME_NONNULL_BEGIN

    @interface YYCache : NSObject

    ...

    - (nullable instancetype)initWithName:(NSString *)name;

    ...

    @end

    NS_ASSUME_NONNULL_END

    接口中 nullable 的是少数,一般都为nonnull,为了防止写一大堆 nonnull,Foundation供了一对宏NS_ASSUME_NONNULL_BEGIN、NS_ASSUME_NONNULL_END,包在里面的对象默认加 nonnull 修饰符,如果是nullable的,只需要把 nullable 的指出来就行

    - (instancetype)init UNAVAILABLE_ATTRIBUTE;

    + (instancetype)new UNAVAILABLE_ATTRIBUTE;

    command+鼠标左键UNAVAILABLE_ATTRIBUTE,

    发现宏定义#define UNAVAILABLE_ATTRIBUTE __attribute__((unavailable)),

    __attribute__是Clang提供的一种源码注解,方便开发者向编译器表达某种要求,括号里是传达某种命令.

    为方便使用,一些常用属性也被Cocoa定义成宏,

    比如UNAVAILABLE_ATTRIBUTE、NS_CLASS_AVAILABLE_IOS(9_0).

    unavailable告诉编译器该方法失效.

    在封装单例或初始化某个类前必须做一些事时,对一些方法禁用是非常不错的选择.

    还可以给个message提示:

    + (instancetype)alloc __attribute__((unavailable("alloc方法不可用,请用initWithName:")));

    - (instancetype)init __attribute__((unavailable("init方法不可用,请用initWithName:")));

    + (instancetype)new __attribute__((unavailable("new方法不可用,请用initWithName:")));

    - (instancetype)copy __attribute__((unavailable("copy方法不可用,请用initWithName:")));

    本文只是简单剖析,接下来会分析YYMemoryCache实现原理.

    References

    http://blog.sunnyxx.com/2016/05/14/clang-attributes/

    http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/

  • 相关阅读:
    MS Office CVE-2015-1641 恶意 Exploit 样本分析
    Qbot回归,已感染5.4万台计算机
    工具推荐:Backdoor-apk,安卓APK文件后门测试工具
    安卓微信、QQ自带浏览器 UXSS 漏洞
    延迟注入工具(python)
    小白欢乐多——记ssctf的几道题目
    使用转义防御XSS
    富文本存储型XSS的模糊测试之道
    k8s故障总结
    CentOS7.6部署k8s环境
  • 原文地址:https://www.cnblogs.com/fengmin/p/5579425.html
Copyright © 2011-2022 走看看