首次提交
This commit is contained in:
45
SweetParty/常用工具/svga缓存类/AOESVGAEntity.h
Executable file
45
SweetParty/常用工具/svga缓存类/AOESVGAEntity.h
Executable file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// AOESVGAEntity.h
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AOESVGAEntity : NSObject
|
||||
|
||||
/**
|
||||
svga文件版本:如果存在本地存储,可能出现URL相同但服务端文件已经更新
|
||||
*/
|
||||
@property (nonatomic, strong)NSString *svga_version;
|
||||
|
||||
/**
|
||||
SVGA URL 网络/本地
|
||||
*/
|
||||
@property (nonatomic, strong)NSString *svga_url;
|
||||
|
||||
/**
|
||||
SVGA 标题
|
||||
*/
|
||||
@property (nonatomic, strong)NSString *svga_title;
|
||||
|
||||
/**
|
||||
SVGA 描述
|
||||
*/
|
||||
@property (nonatomic, strong)NSString *svga_description;
|
||||
|
||||
/**
|
||||
SVGA 基于父视图的位置
|
||||
*/
|
||||
@property (nonatomic, assign)CGRect svga_forSupviewRect;
|
||||
|
||||
/**
|
||||
SVGA 显示的父视图
|
||||
*/
|
||||
@property (nonatomic, strong)id superView;
|
||||
|
||||
|
||||
@end
|
||||
13
SweetParty/常用工具/svga缓存类/AOESVGAEntity.m
Executable file
13
SweetParty/常用工具/svga缓存类/AOESVGAEntity.m
Executable file
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// AOESVGAEntity.m
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AOESVGAEntity.h"
|
||||
|
||||
@implementation AOESVGAEntity
|
||||
|
||||
@end
|
||||
26
SweetParty/常用工具/svga缓存类/AOESVGAQueue.h
Executable file
26
SweetParty/常用工具/svga缓存类/AOESVGAQueue.h
Executable file
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// AOESVGAQueue.h
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "AOESVGAEntity.h"
|
||||
|
||||
@interface AOESVGAQueue : NSObject
|
||||
|
||||
/**
|
||||
是否开启本地存储
|
||||
*/
|
||||
@property (nonatomic, assign)BOOL isMemory;
|
||||
|
||||
/**
|
||||
添加动画进队列
|
||||
|
||||
@param entity 动画信息对象
|
||||
*/
|
||||
-(void)addSVGAInQueue:(AOESVGAEntity *)entity;
|
||||
|
||||
@end
|
||||
134
SweetParty/常用工具/svga缓存类/AOESVGAQueue.m
Executable file
134
SweetParty/常用工具/svga缓存类/AOESVGAQueue.m
Executable file
@@ -0,0 +1,134 @@
|
||||
//
|
||||
// AOESVGAQueue.m
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#import "AOESVGAQueue.h"
|
||||
|
||||
#if __has_include(<SVGAPlayer/SVGA.h>)
|
||||
#import <SVGAPlayer/SVGA.h>
|
||||
#elif __has_include("SVGAPlayer/SVGA.h")
|
||||
#import "SVGAPlayer/SVGA.h"
|
||||
#else
|
||||
#import "SVGA.h"
|
||||
#endif
|
||||
|
||||
#import "SVGAParser+AOESVGAMemory.h"
|
||||
|
||||
@interface AOESVGAQueue ()<SVGAPlayerDelegate>
|
||||
|
||||
@property (nonatomic, strong)NSOperationQueue *queue;
|
||||
|
||||
@property (nonatomic, strong) SVGAPlayer *aPlayer;
|
||||
@property (nonatomic, strong) SVGAParser *parser;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AOESVGAQueue
|
||||
|
||||
-(void)addSVGAInQueue:(AOESVGAEntity *)entity{
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
[self.queue addOperationWithBlock:^{
|
||||
|
||||
//暂停当前队列操作,SVGAParser 内部也会进入队列异步等,防止当前动画被后续动画覆盖
|
||||
[weakSelf.queue setSuspended:YES];
|
||||
|
||||
//更新UI 需要执行到主线程
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
[weakSelf playSVGA:entity];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
-(void)playSVGA:(AOESVGAEntity *)entity{
|
||||
|
||||
self.aPlayer.frame = entity.svga_forSupviewRect;
|
||||
[entity.superView addSubview:self.aPlayer];
|
||||
|
||||
__weak typeof(self)weakSelf = self;
|
||||
|
||||
if (self.isMemory == YES) {
|
||||
|
||||
[self.parser parseMemoryWithURL:[NSURL URLWithString:entity.svga_url] Version:entity.svga_version completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (videoItem != nil) {
|
||||
|
||||
weakSelf.aPlayer.videoItem = videoItem;
|
||||
[weakSelf.aPlayer startAnimation];
|
||||
}
|
||||
|
||||
} failureBlock:nil];
|
||||
}else{
|
||||
|
||||
[self.parser parseWithURL:[NSURL URLWithString:entity.svga_url] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (videoItem != nil) {
|
||||
|
||||
weakSelf.aPlayer.videoItem = videoItem;
|
||||
[weakSelf.aPlayer startAnimation];
|
||||
}
|
||||
|
||||
} failureBlock:nil];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - <SVGAPlayerDelegate>
|
||||
-(void)svgaPlayerDidFinishedAnimation:(SVGAPlayer *)player{
|
||||
|
||||
//开启队列执行下一个动画
|
||||
[self.queue setSuspended:NO];
|
||||
|
||||
if (self.queue.operations.count==0) {
|
||||
|
||||
//从父视图移除SVGAPlayer 防止按钮遮挡
|
||||
[self.aPlayer removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - dealloc
|
||||
-(void)dealloc{
|
||||
|
||||
NSLog(@"AOESVGAQueue dealloc");
|
||||
}
|
||||
|
||||
#pragma mark - setter/getter
|
||||
-(SVGAPlayer *)aPlayer{
|
||||
|
||||
if (!_aPlayer) {
|
||||
|
||||
_aPlayer = [[SVGAPlayer alloc]init];
|
||||
_aPlayer.delegate = self;
|
||||
_aPlayer.loops = 1;
|
||||
_aPlayer.clearsAfterStop = YES;
|
||||
}
|
||||
|
||||
return _aPlayer;
|
||||
}
|
||||
|
||||
-(SVGAParser *)parser{
|
||||
|
||||
if (!_parser) {
|
||||
|
||||
_parser = [[SVGAParser alloc]init];
|
||||
}
|
||||
|
||||
return _parser;
|
||||
}
|
||||
|
||||
-(NSOperationQueue *)queue{
|
||||
|
||||
if (!_queue) {
|
||||
|
||||
_queue = [[NSOperationQueue alloc]init];
|
||||
_queue.maxConcurrentOperationCount = 1;
|
||||
}
|
||||
|
||||
return _queue;
|
||||
}
|
||||
|
||||
@end
|
||||
45
SweetParty/常用工具/svga缓存类/SVGAParser+AOESVGAMemory.h
Executable file
45
SweetParty/常用工具/svga缓存类/SVGAParser+AOESVGAMemory.h
Executable file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// SVGAParser+AOESVGAMemory.h
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#if __has_include(<SVGAPlayer/SVGAParser.h>)
|
||||
#import <SVGAPlayer/SVGAParser.h>
|
||||
#elif __has_include("SVGAPlayer/SVGAParser.h")
|
||||
#import "SVGAPlayer/SVGAParser.h"
|
||||
#else
|
||||
#import "SVGAParser.h"
|
||||
#endif
|
||||
|
||||
#define AOESVGAMemoryDir @"SVGA" //设置Document 下SVGA文件存储路径
|
||||
|
||||
@interface SVGAParser (AOESVGAMemory)
|
||||
|
||||
/**
|
||||
通过url加载svga动画,设置svga文件存储
|
||||
|
||||
@param URL url
|
||||
@param completionBlock 成功回调
|
||||
@param failureBlock 失败回调
|
||||
*/
|
||||
- (void)parseMemoryWithURL:(nonnull NSURL *)URL
|
||||
Version:(NSString *_Nullable)version
|
||||
completionBlock:(void ( ^ _Nonnull )(SVGAVideoEntity * _Nullable videoItem))completionBlock
|
||||
failureBlock:(void ( ^ _Nullable)(NSError * _Nullable error))failureBlock;
|
||||
|
||||
/**
|
||||
本地存储大小
|
||||
|
||||
@param sucBlock size k
|
||||
*/
|
||||
+ (void)memoryAllSzie:(void (^ _Nullable)(NSUInteger size))sucBlock;
|
||||
|
||||
/**
|
||||
移除所有本地的SVGA相关文件
|
||||
*/
|
||||
+ (void)removeAllMemorySvgas:(void ( ^ _Nullable)(BOOL suc))sucBlock;
|
||||
|
||||
@end
|
||||
322
SweetParty/常用工具/svga缓存类/SVGAParser+AOESVGAMemory.m
Executable file
322
SweetParty/常用工具/svga缓存类/SVGAParser+AOESVGAMemory.m
Executable file
@@ -0,0 +1,322 @@
|
||||
//
|
||||
// SVGAParser+AOESVGAMemory.m
|
||||
// AOESVGASimple
|
||||
//
|
||||
// Created by 夏宁忠 on 2018/3/9.
|
||||
// Copyright © 2018年 夏宁忠. All rights reserved.
|
||||
//
|
||||
|
||||
#import "SVGAParser+AOESVGAMemory.h"
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
@implementation SVGAParser (AOESVGAMemory)
|
||||
|
||||
-(void)parseMemoryWithURL:(NSURL *)URL Version:(NSString * _Nullable)version completionBlock:(void (^ _Nonnull)(SVGAVideoEntity * _Nullable))completionBlock failureBlock:(void (^ _Nullable)(NSError * _Nullable))failureBlock{
|
||||
|
||||
NSFileManager * fileMgr = [NSFileManager defaultManager];
|
||||
|
||||
NSString *dir = [self memorySVGADir:URL];
|
||||
NSString * svgaFilePath = [dir stringByAppendingString:[NSString stringWithFormat:@"/%@.svga",[self MD5StringExt:URL.absoluteString]]];
|
||||
NSString * versionFilePath = [dir stringByAppendingString:@"/version.text"];
|
||||
|
||||
if ([fileMgr fileExistsAtPath:svgaFilePath]) { //存在
|
||||
|
||||
//检测版本文件是否存在,如果存在version文件 对比version
|
||||
if ([fileMgr fileExistsAtPath:versionFilePath]) {
|
||||
|
||||
NSString * versionStr = [NSString stringWithContentsOfFile:versionFilePath encoding:NSUTF8StringEncoding error:nil];
|
||||
if ([versionStr isEqualToString:version]) {
|
||||
|
||||
//读取本地
|
||||
NSURL * locationUrl = [NSURL fileURLWithPath:svgaFilePath];
|
||||
[self parseWithURL:locationUrl completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (completionBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
completionBlock(videoItem);
|
||||
}];
|
||||
}
|
||||
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}];
|
||||
|
||||
}else{ //版本不一致
|
||||
|
||||
//重新下载然后加载
|
||||
//不存在version文件 重新下载svga,并创建version文件 写入版本号
|
||||
[[[NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if (error == nil && data != nil) {
|
||||
|
||||
[self parseWithURL:URL completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (completionBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
completionBlock(videoItem);
|
||||
}];
|
||||
}
|
||||
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
|
||||
//svga写入文件
|
||||
BOOL svgaWrite = [data writeToFile:svgaFilePath atomically:YES];
|
||||
if (svgaWrite == NO) {
|
||||
|
||||
[fileMgr removeItemAtPath:svgaFilePath error:nil];
|
||||
}
|
||||
|
||||
//版本写入文件
|
||||
NSString * svga_version = (version && ![version isEqualToString:@""]) ? version : @"0";
|
||||
BOOL versionWrite = [svga_version writeToFile:versionFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
|
||||
if (versionWrite == NO) {
|
||||
|
||||
[fileMgr removeItemAtPath:versionFilePath error:nil];
|
||||
}
|
||||
});
|
||||
|
||||
}else {
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}] resume];
|
||||
}
|
||||
}else{
|
||||
|
||||
//不存在version文件 重新下载svga,并创建version文件 写入版本号
|
||||
[[[NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if (error == nil && data != nil) {
|
||||
|
||||
[self parseWithURL:URL completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (completionBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
completionBlock(videoItem);
|
||||
}];
|
||||
}
|
||||
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
|
||||
//svga写入文件
|
||||
BOOL svgaWrite = [data writeToFile:svgaFilePath atomically:YES];
|
||||
if (svgaWrite == NO) {
|
||||
|
||||
[fileMgr removeItemAtPath:svgaFilePath error:nil];
|
||||
}
|
||||
|
||||
//版本写入文件
|
||||
NSString * svga_version = (version && ![version isEqualToString:@""]) ? version : @"0";
|
||||
//检测是否存在Version文件,如果没有创建并写入
|
||||
if (![fileMgr fileExistsAtPath:versionFilePath]) {
|
||||
|
||||
[fileMgr createFileAtPath:versionFilePath contents:nil attributes:nil];
|
||||
}
|
||||
BOOL versionWrite = [svga_version writeToFile:versionFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
|
||||
if (versionWrite == NO) {
|
||||
|
||||
[fileMgr removeItemAtPath:versionFilePath error:nil];
|
||||
}
|
||||
});
|
||||
|
||||
}else {
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}] resume];
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//不存在svga 下载svga动画
|
||||
//svga写入文件下载 写入
|
||||
[[[NSURLSession sharedSession] dataTaskWithURL:URL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||
if (error == nil && data != nil) {
|
||||
|
||||
[self parseWithURL:URL completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
|
||||
if (completionBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
|
||||
completionBlock(videoItem);
|
||||
}];
|
||||
}
|
||||
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
if (failureBlock) {
|
||||
|
||||
failureBlock(error);
|
||||
}
|
||||
}];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
|
||||
//svga写入文件
|
||||
[fileMgr createFileAtPath:svgaFilePath contents:data attributes:nil];
|
||||
|
||||
//版本写入文件
|
||||
NSString * svga_version = (version && ![version isEqualToString:@""]) ? version : @"0";
|
||||
//检测是否存在Version文件,如果没有创建并写入
|
||||
if (![fileMgr fileExistsAtPath:versionFilePath]) {
|
||||
|
||||
[fileMgr createFileAtPath:versionFilePath contents:nil attributes:nil];
|
||||
}
|
||||
BOOL versionWrite = [svga_version writeToFile:versionFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
|
||||
if (versionWrite == NO) {
|
||||
|
||||
[fileMgr removeItemAtPath:versionFilePath error:nil];
|
||||
}
|
||||
});
|
||||
|
||||
}else {
|
||||
if (failureBlock) {
|
||||
|
||||
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
|
||||
failureBlock(error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
}] resume];
|
||||
}
|
||||
|
||||
+(void)memoryAllSzie:(void (^)(NSUInteger))sucBlock{
|
||||
|
||||
//异步计算
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
|
||||
NSString *memoryDirPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingString:[NSString stringWithFormat:@"/%@",AOESVGAMemoryDir]];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
BOOL dir = NO;
|
||||
[fileManager fileExistsAtPath:memoryDirPath isDirectory:&dir];
|
||||
|
||||
NSUInteger totalByteSize = 0;
|
||||
|
||||
if (dir) { //存在SVGA文件夹 计算存储
|
||||
|
||||
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:memoryDirPath];
|
||||
for (NSString *subpath in enumerator) {
|
||||
// 全路径
|
||||
NSString *fullSubpath = [memoryDirPath stringByAppendingPathComponent:subpath];
|
||||
// 累加文件大小
|
||||
totalByteSize += [fileManager attributesOfItemAtPath:fullSubpath error:nil].fileSize;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
if (sucBlock) {
|
||||
|
||||
sucBlock(totalByteSize);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+(void)removeAllMemorySvgas:(void (^)(BOOL))sucBlock{
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
|
||||
NSString *memoryDirPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingString:[NSString stringWithFormat:@"/%@",AOESVGAMemoryDir]];
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
BOOL dir = NO;
|
||||
[fileManager fileExistsAtPath:memoryDirPath isDirectory:&dir];
|
||||
|
||||
BOOL isSuccess = NO;
|
||||
if (dir) { //存在文件夹
|
||||
|
||||
isSuccess = [fileManager removeItemAtPath:memoryDirPath error:nil];
|
||||
|
||||
}else{
|
||||
|
||||
isSuccess = YES;
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (sucBlock) {
|
||||
|
||||
sucBlock(isSuccess);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
//文件夹SVGA 不存在创建
|
||||
-(nullable NSString *)memorySVGADir:(NSURL *)url{
|
||||
|
||||
NSFileManager * fileMgr = [NSFileManager defaultManager];
|
||||
NSString *memoryDir = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingString:[NSString stringWithFormat:@"/%@/%@",AOESVGAMemoryDir,[self MD5StringExt:url.absoluteString]]];
|
||||
|
||||
BOOL dir = NO;
|
||||
[fileMgr fileExistsAtPath:memoryDir isDirectory:&dir];
|
||||
|
||||
if (dir == NO) { //创建文件夹
|
||||
|
||||
[fileMgr createDirectoryAtPath:memoryDir withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
return memoryDir;
|
||||
}
|
||||
|
||||
- (NSString *)MD5StringExt:(NSString *)str {
|
||||
|
||||
const char *cstr = [str UTF8String];
|
||||
unsigned char result[16];
|
||||
CC_MD5(cstr, (CC_LONG)strlen(cstr), result);
|
||||
return [NSString stringWithFormat:
|
||||
@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
result[0], result[1], result[2], result[3],
|
||||
result[4], result[5], result[6], result[7],
|
||||
result[8], result[9], result[10], result[11],
|
||||
result[12], result[13], result[14], result[15]
|
||||
];
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user