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
- 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后被删除。
- 获取数据方法- (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];
}
}