Weex开发技巧weex社区

weex在iOS中的扩展模块源码分析(以Storage扩展为例)

2017-12-06  本文已影响66人  KChuck

Weex在 iOS 下选择了 JavaScriptCore 内核,解析Javascript代码,最后在iOS native端进行界面渲染、数据存储或网络通信等。即,最后在iOS 客户端执行的还是原生的OC或Swift代码。

以Storage扩展为例,在Xcode工程中的实现是WXStorageModule类。在.h文件中有以下方法。

#import "WXModuleProtocol.h"

@interface WXStorageModule : NSObject <WXModuleProtocol>

- (void)length:(WXModuleCallback)callback;

- (void)getAllKeys:(WXModuleCallback)callback;

- (void)setItem:(NSString *)key value:(NSString *)value callback:(WXModuleCallback)callback;

- (void)setItemPersistent:(NSString *)key value:(NSString *)value callback:(WXModuleCallback)callback;

- (void)getItem:(NSString *)key callback:(WXModuleCallback)callback;

- (void)removeItem:(NSString *)key callback:(WXModuleCallback)callback;

@end
  1. length:方法,获取已经存储数据的条数,
- (void)length:(WXModuleCallback)callback
{
    if (callback) {
        callback(@{@"result":@"success",@"data":@([[WXStorageModule memory] count])});
    }
}

2.getAllKeys:获取存储数据的全部key值,每个key对应一条数据。

- (void)getAllKeys:(WXModuleCallback)callback
{
    if (callback) {
        callback(@{@"result":@"success",@"data":[WXStorageModule memory].allKeys});
    }
}

3.以setItem: value: callback:方法(存储数据),实现的关键是

[self setObject:value forKey:key persistent:NO callback:callback];

- (void)setObject:(NSString *)obj forKey:(NSString *)key persistent:(BOOL)persistent callback:(WXModuleCallback)callback {
    NSString *filePath = [WXStorageModule filePathForKey:key];
    if (obj.length <= WXStorageLineLimit) {
        if ([WXStorageNullValue isEqualToString:self.memory[key]]) {
            [[WXUtility globalCache] removeObjectForKey:key];
            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
        }
        self.memory[key] = obj;
        NSDictionary *dict = [self.memory copy];
        [self write:dict toFilePath:[WXStorageModule filePath]];
        [self setInfo:@{@"persistent":@(persistent),@"size":@(obj.length)} ForKey:key];
        [self updateIndexForKey:key];
        [self checkStorageLimit];
        if (callback) {
            callback(@{@"result":@"success"});
        }
        return;
    }
    //...
}
[self write:dict toFilePath:[WXStorageModule filePath]];

数据最后以数据字典的形式存储在本地文件中,且persistent参数指定了是否持久存储。非持久的数据可能在存储超过5M后被删除。

  1. 获取数据方法- (void)getItem:(NSString *)key callback:(WXModuleCallback)callback ,根据key值去读取本地存储
NSString *value = [self.memory objectForKey:key];
  if ([WXStorageNullValue isEqualToString:value]) {
      value = [[WXUtility globalCache] objectForKey:key];
      if (!value) {
          NSString *filePath = [WXStorageModule filePathForKey:key];
          NSString *contents = [WXUtility stringWithContentsOfFile:filePath];
          if (contents) {
              [[WXUtility globalCache] setObject:contents forKey:key cost:contents.length];
              value = contents;
          }
      }
  }

5.removeItem: 方法则根据key去删除本地对应的存储。

if ([WXStorageNullValue isEqualToString:self.memory[key]]) {
        [self.memory removeObjectForKey:key];
        NSDictionary *dict = [self.memory copy];
        [self write:dict toFilePath:[WXStorageModule filePath]];
        dispatch_async([WXStorageModule storageQueue], ^{
            NSString *filePath = [WXStorageModule filePathForKey:key];
            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
            [[WXUtility globalCache] removeObjectForKey:key];
        });
}

6.存储的数据总大小不能超过5M

static NSUInteger const WXStorageLineLimit            = 1024;
static NSUInteger const WXStorageTotalLimit           = 5 * 1024 * 1024;

检查已存储的数据大小

- (void)checkStorageLimit {
    NSInteger size = [self totalSize] - WXStorageTotalLimit;
    if (size > 0) {
        [self removeItemsBySize:size];
    }
}

如果超过5M,则删去部分非持久(根据存储的persistent字段)存储的数据

- (void)removeItemsBySize:(NSInteger)size {
    NSArray *indexs = [[self indexs] copy];
    if (size < 0 || indexs.count == 0) {
        return;
    }
    
    NSMutableArray *removedKeys = [NSMutableArray array];
    for (NSInteger i = 0; i < indexs.count; i++) {
        NSString *key = indexs[i];
        NSDictionary *info = [self getInfoForKey:key];
        
        // persistent data, can't be removed
        if ([info[@"persistent"] boolValue]) {
            continue;
        }
        
        [removedKeys addObject:key];
        size -= [info[@"size"] integerValue];
        
        if (size < 0) {
            break;
        }
    }
    
    // actually remove data
    for (NSString *key in removedKeys) {
        [self executeRemoveItem:key];
    }
}
上一篇下一篇

猜你喜欢

热点阅读