iOS开发-实现获取下载主题配置动态切换主题

iOS开发-实现获取下载主题配置动态切换主题

iOS开发-实现获取下载主题配置更切换主题,主要是通过请求服务端配置的主题配置、下载主题、解压保存到本地。通知界面获取对应的图片及颜色等。

比如新年主题风格,常见的背景显示红色氛围图片、tabbar显示新年风格的按钮样式、导航条显示红色样式等。
在这里插入图片描述

一、主题Json对应的model

这里使用JsonModel将主题转成model

model代码如下

SDAppThemeConfigViewModel.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>/**Navigation主题样式*/
@interface SDAppThemeConfigNavViewModel : NSObject@property (nonatomic, strong) NSString *backgroundColor;
@property (nonatomic, strong) NSString *backgroundImage;@property (nonatomic, strong) UIImage *t_backgroundImage;@property (nonatomic, strong) NSString *btnImageColor;
@property (nonatomic, strong) NSString *btnTitleColor;
@property (nonatomic, strong) NSString *navTitleColor;@property (nonatomic, strong) NSString *showLine;
@property (nonatomic, strong) NSString *lineColor;@end/**单个tab按钮样式*/
@interface SDAppThemeConfigTabItemViewModel : NSObject@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *titleColor;
@property (nonatomic, strong) NSString *selectedTitleColor;
@property (nonatomic, strong) NSString *icon;
@property (nonatomic, strong) NSString *selectedIcon;@property (nonatomic, strong) UIImage *t_icon;
@property (nonatomic, strong) UIImage *t_selectedIcon;@end/**tabbar样式*/
@interface SDAppThemeConfigTabViewModel : NSObject@property (nonatomic, strong) NSString *backgroundColor;
@property (nonatomic, strong) NSString *backgroundImage;
@property (nonatomic, strong) NSString *showLine;
@property (nonatomic, strong) NSString *lineColor;
@property (nonatomic, strong) NSString *badgeBgColor;@property (nonatomic, strong) UIImage *t_backgroundImage;@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *lianlian;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *guangguang;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *message;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *shop;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *mine;@end/**将本地的主题config.json转成viewmodel*/
@interface SDAppThemeConfigViewModel : NSObject@property (nonatomic, strong) NSString *globalColor;
@property (nonatomic, strong) NSString *globalImage;
@property (nonatomic, strong) SDAppThemeConfigNavViewModel *navigation;
@property (nonatomic, strong) SDAppThemeConfigTabViewModel *tabbar;@property (nonatomic, strong) UIImage *t_globalImage;+ (SDAppThemeConfigViewModel *)themeViewModel:(NSString *)themeJson;+ (SDAppThemeConfigViewModel *)defautThemeViewModel;@end

SDAppThemeConfigViewModel.m

#import "SDAppThemeConfigViewModel.h"
#import <NSObject+YYModel.h>/**Navigation主题样式*/
@implementation SDAppThemeConfigNavViewModel@end/**单个tab按钮样式*/
@implementation SDAppThemeConfigTabItemViewModel@end/**tabbar样式*/
@implementation SDAppThemeConfigTabViewModel@end/**将本地的主题config.json转成viewmodel*/
@implementation SDAppThemeConfigViewModel+ (SDAppThemeConfigViewModel *)themeViewModel:(NSString *)themeJson {return [SDAppThemeConfigViewModel modelWithJSON:themeJson];
}+ (SDAppThemeConfigViewModel *)defautThemeViewModel {SDAppThemeConfigViewModel *viewModel = [[SDAppThemeConfigViewModel alloc] init];SDAppThemeConfigNavViewModel *navConfigViewModel = [[SDAppThemeConfigNavViewModel alloc] init];navConfigViewModel.backgroundColor = @"171013";navConfigViewModel.btnImageColor = @"ffffff";navConfigViewModel.btnTitleColor = @"ffffff";navConfigViewModel.navTitleColor = @"ffffff";viewModel.navigation = navConfigViewModel;return viewModel;
}@end

二、实现下载解压主题

2.1 AFNetworking下载

下载使用的是AFNetworking下载功能。AFNetworking是一个轻量级的iOS网络通信类库。

下载代码:

#pragma mark - Http download
/**请求下载@param aUrl aurl@param aSavePath aSavePath@param aFileName aFileName@param aTag aTag@param downloadprogress downloadprogress@param success success@param failure failure*/
- (void)downloadFileURL:(NSString *)aUrlsavePath:(NSString *)aSavePathfileName:(NSString *)aFileNametag:(NSInteger)aTagdownloadProgress:(void(^)(CGFloat progress))downloadprogresssuccess:(void(^)(NSURLResponse *response,NSString *filePath))successfailure:(void(^)(HttpError * e))failure {NSFileManager *fileManger = [NSFileManager defaultManager];if ([fileManger fileExistsAtPath:[aSavePath stringByAppendingPathComponent:aFileName]]) {//文件存在return;}//2.确定请求的URL地址NSString *requestUrl = [self requestUrlWithPath:aUrl clientType:HttpClientTypeWithOut];NSMutableURLRequest *request = [self.httpManager.requestSerializer requestWithMethod:@"GET" URLString:requestUrl parameters:nil error:nil];__block NSURLSessionDownloadTask *downloadTask = nil;downloadTask = [self.httpManager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {dispatch_async(dispatch_get_main_queue(), ^{downloadprogress(1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);});} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {return [NSURL fileURLWithPath:aSavePath];} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {if(error == nil) {success(response,[filePath path]);} else {//下载失败NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;HttpError *e = [self httpRequestFailure:httpResponse error:error];failure(e);}}];[downloadTask resume];
}

2.2 判断主题版本是否已经下载

在获取主题版本时候,需要判断主题是否存在,如果存在,则直接获取保存的地址。不存在,下载解压当前版本的主题包。

//判断当前主题版本号下是否存在资源文件夹BOOL curThemeExist = [self hasAppThemeVersion:themeModel.curVersion];if (!curThemeExist) {//如果不存在,重新下载解压__block NSString *saveZipPath = [self saveThemeTargetBasePath:themeModel.curVersion];__block NSString *themeUnZipPath = [self saveThemeDirBasePath:themeModel.curVersion];__block NSString *curDownloadurl = themeModel.curDownloadurl;//下载成功NSString *afileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];__block NSString *afilePath = [NSString pathWithComponents:@[saveZipPath, afileName]];[[INHttpClientUtil sharedInstance] downloadFileURL:curDownloadurl savePath:afilePath fileName:afilePath tag:[afilePath hash] downloadProgress:^(CGFloat progress) {} success:^(NSURLResponse *response, NSString *filePath) {//下载成功NSString *fileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];NSString *selFilePath = [NSString pathWithComponents:@[saveZipPath, fileName]];//准备执行解压方法[self onFileSelected:selFilePath unZipPath:themeUnZipPath];} failure:^(HttpError *e) {NSLog(@"failure request :%@",e);}];} else {//如果存在,直接显示__block NSString *saveZipPath = [self saveThemeTargetBasePath:themeModel.curVersion];__block NSString *themeUnZipPath = [self saveThemeDirBasePath:themeModel.curVersion];__block NSString *curDownloadurl = themeModel.curDownloadurl;//下载成功NSString *fileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];NSString *filePath = [NSString pathWithComponents:@[saveZipPath, fileName]];//准备执行解压方法[self unzipCompltion:themeUnZipPath];}

2.2 解压zip主题包

将下载的主题包解压,zip包进行解压。

// 解压
- (void)releaseZipFilesWithUnzipFileAtPath:(NSString *)zipPath destination:(NSString *)unzipPath {NSError *error;// 如果解压成功if ([SSZipArchive unzipFileAtPath:zipPath toDestination:unzipPath overwrite:YES password:nil error:&error delegate:self]) {// 存储主题的色调[self unzipCompltion:unzipPath];} else {NSLog(@"%@",error);}
}

解压完成后得到解压的目录。

2.3 获取到解压的目录地址,将配置的json文件转成对应的model

获取到解压的目录地址,将配置的json文件转成对应的model

/**调用解压文件@param unzipPath 获取地址*/
- (void)unzipCompltion:(NSString *)unzipPath {// 存储主题的色调// 已经存储主题tabbar图片、navigationbar图片、配置文件等等资源NSArray *folders = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:unzipPath error:NULL];NSString *selectedFilePath = unzipPath;NSString *aPath = [folders lastObject];NSString *fullPath = [unzipPath stringByAppendingPathComponent:aPath];selectedFilePath = fullPath;NSString *configPath = [NSString stringWithFormat:@"%@/config.json",selectedFilePath];NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:configPath];NSData *data = [fh readDataToEndOfFile];NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:[SDJsonUtil dictionaryWithJsonString:jsonStr]];NSLog(@"theme config.json:%@",dict);SDAppThemeConfigViewModel *themeViewModel = [SDAppThemeConfigViewModel themeViewModel:jsonStr];themeViewModel.t_globalImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.globalImage];themeViewModel.navigation.t_backgroundImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.navigation.backgroundImage];themeViewModel.tabbar.t_backgroundImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.backgroundImage];themeViewModel.tabbar.lianlian.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.lianlian.icon];themeViewModel.tabbar.lianlian.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.lianlian.selectedIcon];themeViewModel.tabbar.guangguang.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.guangguang.icon];themeViewModel.tabbar.guangguang.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.guangguang.selectedIcon];themeViewModel.tabbar.message.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.message.icon];themeViewModel.tabbar.message.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.message.selectedIcon];themeViewModel.tabbar.mine.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.mine.icon];themeViewModel.tabbar.mine.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.mine.selectedIcon];//配置全局主题[SDAppThemeManager shareInstance].configViewModel = themeViewModel;[[NSNotificationCenter defaultCenter] postNotificationName:K_APP_THEME_CHANGED object:nil userInfo:nil];
}

之后通知界面切换对应的图片及风格图。

2.4 界面添加通知Observer

界面接收到通知后,更新到对应的图片及颜色。
我这里是就写一个切换Tabbar新年主题风格图片。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(systemAppThemeChanged:) name:K_APP_THEME_CHANGED object:nil];

切换Tabbar新年主题风格图片

- (void)updateThemeConfig {//主题,可以更改tabbar样式SDAppThemeConfigViewModel *themeConfigViewModel = [SDAppThemeManager shareInstance].configViewModel;UIImage *backgroundImage;if (themeConfigViewModel.tabbar.t_backgroundImage) {backgroundImage = themeConfigViewModel.tabbar.t_backgroundImage;} else {NSString *bgColor = themeConfigViewModel.tabbar.backgroundColor;backgroundImage = [UIImage imageWithColor:[UIColor colorWithHexString:bgColor] size:CGSizeMake(20.0, 20.0)];backgroundImage = [backgroundImage stretchableImageWithLeftCapWidth:backgroundImage.leftCapWidth*0.5 topCapHeight:backgroundImage.topCapHeight*0.5];}self.sdTabbar.bgroundImage = backgroundImage;NSString *showLine = themeConfigViewModel.tabbar.showLine;self.sdTabbar.showLine = [showLine boolValue];self.sdTabbar.lineColor = [UIColor colorWithHexString:themeConfigViewModel.tabbar.lineColor];UIColor *badgeBGColor = [UIColor colorWithHexString:themeConfigViewModel.tabbar.badgeBgColor];SDTabbarItem *homeItem = [self themeTabbarItem:themeConfigViewModel.tabbar.lianlian];homeItem.identifier = @"home";homeItem.badgeColor = badgeBGColor;SDTabbarItem *addressbookItem = [self themeTabbarItem:themeConfigViewModel.tabbar.message];addressbookItem.identifier = @"addressbook";addressbookItem.badgeColor = badgeBGColor;SDTabbarItem *discoveryItem = [self themeTabbarItem:themeConfigViewModel.tabbar.guangguang];discoveryItem.identifier = @"discovery";discoveryItem.badgeColor = badgeBGColor;SDTabbarItem *mineItem = [self themeTabbarItem:themeConfigViewModel.tabbar.mine];mineItem.identifier = @"mine";mineItem.badgeColor = badgeBGColor;[self.sdTabbar updateTabbarStyle:homeItem];[self.sdTabbar updateTabbarStyle:addressbookItem];[self.sdTabbar updateTabbarStyle:discoveryItem];[self.sdTabbar updateTabbarStyle:mineItem];
}- (void)systemAppThemeChanged:(NSNotification *)notification {[self updateThemeConfig];
}- (SDTabbarItem *)themeTabbarItem:(SDAppThemeConfigTabItemViewModel *)itemViewModel {SDTabbarItem *tabbarItem = [[SDTabbarItem alloc] init];tabbarItem.title = itemViewModel.title;tabbarItem.titleColor = [UIColor colorWithHexString:itemViewModel.titleColor];tabbarItem.selectedTitleColor = [UIColor colorWithHexString:itemViewModel.selectedTitleColor];tabbarItem.image = itemViewModel.t_icon;tabbarItem.selectedImage = itemViewModel.t_selectedIcon;return tabbarItem;
}

tabbar的按钮更新:根据对应的identifier切换到对应的图片及颜色配置。

/**更新tabbar样式@param tabbarItem item*/
- (void)updateTabbarStyle:(SDTabbarItem *)tabbarItem {for (UIView *subView in self.subviews) {if ([subView isKindOfClass:[SDTabbarButton class]]) {SDTabbarButton *tabbarButton = (SDTabbarButton *)subView;SDTabbarItem *item = tabbarButton.tabbarItem;if (tabbarItem.identifier && [tabbarItem.identifier isEqualToString:item.identifier]) {//更新tabbar[item copyClone:tabbarItem];tabbarButton.tabbarItem = item;break;}}}
}

三、将model序列化存储到本地目录

将主题数据序列号存储到本地目录,方便下次打开APP进行获取。

SDAppThemeConfigDbManager.h

#import <Foundation/Foundation.h>
#import "SDAppThemeManager.h"@interface SDAppThemeConfigDbManager : NSObject+ (id)shareInstance;- (SDAppThemeViewModel *)getAppThemeViewModelFromDb;- (void)saveAppThemeViewModelToDb:(SDAppThemeViewModel *)info;@end

SDAppThemeConfigDbManager.m

#import "SDAppThemeConfigDbManager.h"static NSString *appThemeConfigPath = @"sdAppThemeConfigPath";
static SDAppThemeConfigDbManager *instance = nil;@implementation SDAppThemeConfigDbManager+ (id)shareInstance
{static dispatch_once_t predicate;dispatch_once(&predicate,^{instance = [[self alloc] init];});return instance;
}- (NSString *)getAppThemeConfigPath
{NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentPath = [paths objectAtIndex:0];NSString *path = [documentPath stringByAppendingPathComponent:appThemeConfigPath];return path;
}- (SDAppThemeViewModel *)getAppThemeViewModelFromDb {NSString *dataFile = [self getAppThemeConfigPath];@try {SDAppThemeViewModel *viewModel = [NSKeyedUnarchiver unarchiveObjectWithFile:dataFile];if (viewModel) {return viewModel;}} @catch (NSException *e) {}return nil;
}- (void)saveAppThemeViewModelToDb:(SDAppThemeViewModel *)info {NSData *data = [NSKeyedArchiver archivedDataWithRootObject:info];NSString *dataFile = [self getAppThemeConfigPath];BOOL isSave = [data writeToFile:dataFile atomically:YES];if (isSave) {NSLog(@"存储成功");} else {NSLog(@"存储失败");}
}@end

四、完整实现代码

  • 需要用到主题Manager:SDAppThemeManager

SDAppThemeManager.h

#import <Foundation/Foundation.h>
//#import "SDThemeConfigRequest.h"
#import "SDAppThemeConfigViewModel.h"/**获取的app主题model,app主题颜色版本号*/
@interface SDAppThemeViewModel : NSObject<NSCoding>@property (nonatomic, strong) NSString *curDownloadurl;     //当前版本的下载地址
@property (nonatomic, strong) NSString *curVersion;         //当前app主题颜色版本号@property (nonatomic, strong) NSString *nextDownloadurl;    //下一版本的下载地址
@property (nonatomic, strong) NSString *nextVersion;        //下一版本app主题颜色版本号@end@interface SDAppThemeManager : NSObject+ (instancetype)shareInstance;@property (nonatomic, strong) SDAppThemeConfigViewModel *configViewModel; //当前版本控制文件/**从服务器端加载APP主题接口*/
- (void)loadAppThemeConfig;/**加载系统主题资源*/
- (void)loadCacheThemeResource;@end

SDAppThemeManager.m

#import "SDAppThemeManager.h"
#import "SDAppThemeConfigDbManager.h"
#import "SDAppThemeDownloadManager.h"
#import "INHttpClientUtil.h"@implementation SDAppThemeViewModel- (id)init {self = [super init];if (self) {}return self;
}- (id)initWithCoder:(NSCoder *)aDecoder
{self = [super init];if (self) {self.curDownloadurl = [aDecoder decodeObjectForKey:@"kAppThemeCurDownloadurl"];self.curVersion = [aDecoder decodeObjectForKey:@"kAppThemeCurVersion"];self.nextDownloadurl = [aDecoder decodeObjectForKey:@"kAppThemeNextDownloadurl"];self.nextVersion = [aDecoder decodeObjectForKey:@"kAppThemeNextVersion"];}return self;
}- (void)encodeWithCoder:(NSCoder *)aCoder
{[aCoder encodeObject:_curDownloadurl forKey:@"kAppThemeCurDownloadurl"];[aCoder encodeObject:_curVersion forKey:@"kAppThemeCurVersion"];[aCoder encodeObject:_nextDownloadurl forKey:@"kAppThemeNextDownloadurl"];[aCoder encodeObject:_nextVersion forKey:@"kAppThemeNextVersion"];
}- (void)clear {self.curDownloadurl = nil;self.curVersion = nil;self.nextDownloadurl = nil;self.nextVersion = nil;
}@endstatic SDAppThemeManager *shareInstance = nil;@implementation SDAppThemeManager+ (instancetype)shareInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{shareInstance = [[SDAppThemeManager alloc] init];shareInstance.configViewModel = [SDAppThemeConfigViewModel defautThemeViewModel];});return shareInstance;
}/**从服务器端加载APP主题接口*/
- (void)loadAppThemeConfig {[[INHttpClientUtil sharedInstance] getWithClientType:HttpClientTypeDefault url:@"/v1/api/theme/system" params:nil success:^(id responseObj) {NSString *code = [NSString stringWithFormat:@"%@",responseObj[@"code"]];if ([@"0" isEqualToString:code] && responseObj[@"data"]) {NSString *curDownloadurl = responseObj[@"data"][@"curDownloadurl"];NSString *curVersion = responseObj[@"data"][@"curVersion"];NSString *nextDownloadurl = responseObj[@"data"][@"nextDownloadurl"];NSString *nextVersion = responseObj[@"data"][@"nextVersion"];SDAppThemeViewModel *themeViewModel = [[SDAppThemeViewModel alloc] init];themeViewModel.curDownloadurl = nextDownloadurl;themeViewModel.curVersion = @"2016.10.27";themeViewModel.nextDownloadurl = nextDownloadurl;themeViewModel.nextVersion = nextVersion;[[SDAppThemeConfigDbManager shareInstance] saveAppThemeViewModelToDb:themeViewModel];[[SDAppThemeDownloadManager shareInstance] downloadThemeZipPackage:themeViewModel];}} failure:^(HttpError *e) {DLog(@"request:%@",e);}];
}/**加载系统主题资源*/
- (void)loadCacheThemeResource {[[SDAppThemeDownloadManager shareInstance] loadCacheThemeResource];
}@end
  • 需要用到主题下载类SDAppThemeDownloadManager

SDAppThemeDownloadManager.h

#import <Foundation/Foundation.h>
//#import "SDThemeConfigRequest.h"
#import "SDAppThemeManager.h"
#import "SDAppThemeConfigViewModel.h"
#import "SDAppThemeConfigDbManager.h"#define K_APP_THEME_CHANGED @"K_APP_THEME_CHANGED"
#define K_DEFAULT_APP_THEME_VERSION @"1.0.0"@interface SDAppThemeDownloadManager : NSObject+ (instancetype)shareInstance;- (void)downloadThemeZipPackage:(SDAppThemeViewModel *)themeModel;/**加载系统主题资源*/
- (void)loadCacheThemeResource;@end

SDAppThemeDownloadManager.m

#import "SDAppThemeDownloadManager.h"
#import "SDJsonUtil.h"
//#import "NSString+ext.h"
#import <SSZipArchive/SSZipArchive.h>
#import "SDAppThemeManager.h"
#import "INHttpClientUtil.h"static SDAppThemeDownloadManager *manager = nil;@interface SDAppThemeDownloadManager () <SSZipArchiveDelegate>@end@implementation SDAppThemeDownloadManager+ (instancetype)shareInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[SDAppThemeDownloadManager alloc] init];});return manager;
}- (void)downloadThemeZipPackage:(SDAppThemeViewModel *)themeModel {//判断当前主题版本号下是否存在资源文件夹BOOL curThemeExist = [self hasAppThemeVersion:themeModel.curVersion];if (!curThemeExist) {//如果不存在,重新下载解压__block NSString *saveZipPath = [self saveThemeTargetBasePath:themeModel.curVersion];__block NSString *themeUnZipPath = [self saveThemeDirBasePath:themeModel.curVersion];__block NSString *curDownloadurl = themeModel.curDownloadurl;//下载成功NSString *afileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];__block NSString *afilePath = [NSString pathWithComponents:@[saveZipPath, afileName]];[[INHttpClientUtil sharedInstance] downloadFileURL:curDownloadurl savePath:afilePath fileName:afilePath tag:[afilePath hash] downloadProgress:^(CGFloat progress) {} success:^(NSURLResponse *response, NSString *filePath) {//下载成功NSString *fileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];NSString *selFilePath = [NSString pathWithComponents:@[saveZipPath, fileName]];//准备执行解压方法[self onFileSelected:selFilePath unZipPath:themeUnZipPath];} failure:^(HttpError *e) {NSLog(@"failure request :%@",e);}];} else {//如果存在,直接显示__block NSString *saveZipPath = [self saveThemeTargetBasePath:themeModel.curVersion];__block NSString *themeUnZipPath = [self saveThemeDirBasePath:themeModel.curVersion];__block NSString *curDownloadurl = themeModel.curDownloadurl;//下载成功NSString *fileName = [[NSURL URLWithString:curDownloadurl] lastPathComponent];NSString *filePath = [NSString pathWithComponents:@[saveZipPath, fileName]];//准备执行解压方法[self unzipCompltion:themeUnZipPath];}/*//判断下一主题版本号下是否存在资源文件夹中BOOL nextThemeExist = [self hasAppThemeVersion:themeModel.nextVersion];if (!nextThemeExist) {//如果不存在,重新下载解压__block NSString *saveZipPath = [self saveThemeTargetBasePath:themeModel.nextVersion];[[HttpClient sharedInstance] downloadFileURL:themeModel.curDownloadurl savePath:saveZipPath fileName:saveZipPath tag:[saveZipPath hash] success:^(id responseObj) {//下载成功} failure:^(HttpException *e) {//下载失败}];}*/
}// 解压
- (void)releaseZipFilesWithUnzipFileAtPath:(NSString *)zipPath destination:(NSString *)unzipPath {NSError *error;// 如果解压成功if ([SSZipArchive unzipFileAtPath:zipPath toDestination:unzipPath overwrite:YES password:nil error:&error delegate:self]) {// 存储主题的色调[self unzipCompltion:unzipPath];} else {NSLog(@"%@",error);}
}/**调用解压文件@param unzipPath 获取地址*/
- (void)unzipCompltion:(NSString *)unzipPath {// 存储主题的色调// 已经存储主题tabbar图片、navigationbar图片、配置文件等等资源NSArray *folders = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:unzipPath error:NULL];NSString *selectedFilePath = unzipPath;NSString *aPath = [folders lastObject];NSString *fullPath = [unzipPath stringByAppendingPathComponent:aPath];selectedFilePath = fullPath;NSString *configPath = [NSString stringWithFormat:@"%@/config.json",selectedFilePath];NSFileHandle *fh = [NSFileHandle fileHandleForReadingAtPath:configPath];NSData *data = [fh readDataToEndOfFile];NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:[SDJsonUtil dictionaryWithJsonString:jsonStr]];NSLog(@"theme config.json:%@",dict);SDAppThemeConfigViewModel *themeViewModel = [SDAppThemeConfigViewModel themeViewModel:jsonStr];themeViewModel.t_globalImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.globalImage];themeViewModel.navigation.t_backgroundImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.navigation.backgroundImage];themeViewModel.tabbar.t_backgroundImage = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.backgroundImage];themeViewModel.tabbar.lianlian.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.lianlian.icon];themeViewModel.tabbar.lianlian.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.lianlian.selectedIcon];themeViewModel.tabbar.guangguang.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.guangguang.icon];themeViewModel.tabbar.guangguang.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.guangguang.selectedIcon];themeViewModel.tabbar.message.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.message.icon];themeViewModel.tabbar.message.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.message.selectedIcon];themeViewModel.tabbar.mine.t_icon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.mine.icon];themeViewModel.tabbar.mine.t_selectedIcon = [self imageWithDocumentoryName:[NSString stringWithFormat:@"%@",selectedFilePath] imageName:themeViewModel.tabbar.mine.selectedIcon];//配置全局主题[SDAppThemeManager shareInstance].configViewModel = themeViewModel;[[NSNotificationCenter defaultCenter] postNotificationName:K_APP_THEME_CHANGED object:nil userInfo:nil];
}/**准备执行解压方法@param selectedPath 原先文件路径@param unZipPath 解压文件路径*/
- (void)onFileSelected:(NSString *)selectedPath unZipPath:(NSString *)unZipPath {NSURL *fileURL = [NSURL fileURLWithPath:selectedPath];NSString *fileNameComponent = fileURL.lastPathComponent;// 获取文件的扩展名NSString *extension = [[fileNameComponent pathExtension] lowercaseString];// 如果是zip类型的压缩包文件,则进行解压if ([extension isEqualToString:@"zip"]) {// 设置解压路径[self releaseZipFilesWithUnzipFileAtPath:selectedPath destination:unZipPath];}
}/**判断当前path路径是否存在@param themeVersion 主题版本号@return 是否文件*/
- (BOOL)hasAppThemeVersion:(NSString *)themeVersion {NSString *pathOfLibrary = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];NSString *path = [pathOfLibrary stringByAppendingPathComponent:[NSString stringWithFormat:@"dftheme-%@",themeVersion]];NSArray *folders = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:NULL];if (!(folders && folders.count > 0)) {return NO;}NSString *aPath = [folders lastObject];NSString *fullPath = [path stringByAppendingPathComponent:aPath];NSFileManager *fileManager = [NSFileManager defaultManager];BOOL result = [fileManager fileExistsAtPath:fullPath];return result;
}/**主题未解压下载目录@param themeVersion 主题版本号@return 最后path*/
- (NSString *)saveThemeTargetBasePath:(NSString *)themeVersion {NSString *pathOfLibrary = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];NSString *path = [pathOfLibrary stringByAppendingPathComponent:[NSString stringWithFormat:@"dfThemesZip-%@",themeVersion]];[self createDirectory:path];return path;
}/**主题解压目录@param themeVersion 主题版本号@return 最后path*/
- (NSString *)saveThemeDirBasePath:(NSString *)themeVersion {NSString *pathOfLibrary = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];NSString *path = [pathOfLibrary stringByAppendingPathComponent:[NSString stringWithFormat:@"dftheme-%@",themeVersion]];[self createDirectory:path];return path;
}- (void)createDirectory:(NSString *)path {NSError *error = nil;[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YESattributes:nil error:&error];if (error) {NSLog(@"Create directory error: %@", error);}
}/**获取使用存储在沙盒里的图片@param documentoryName 文件目录@param imageName 图片名字@return 图片*/
- (UIImage *)imageWithDocumentoryName:(NSString *)documentoryNameimageName:(NSString *)imageName {// 如果文件名不存在或者文件名为空,则返回空if (!imageName || [imageName isEqualToString:@""]) {return nil;}NSString *imgPath = [documentoryName stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",imageName]];UIImage *image = [UIImage imageWithContentsOfFile:imgPath];if (image) {return image;}return [UIImage imageNamed:imageName];
}/**加载系统主题资源*/
- (void)loadCacheThemeResource {SDAppThemeViewModel *themeVersionViewModel = [[SDAppThemeConfigDbManager shareInstance] getAppThemeViewModelFromDb];if (themeVersionViewModel && ![K_DEFAULT_APP_THEME_VERSION isEqualToString:themeVersionViewModel.curVersion]) {[self downloadThemeZipPackage:themeVersionViewModel];}
}

@end

  • 需要用到主题数据:SDAppThemeConfigViewModel

SDAppThemeConfigViewModel.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>/**Navigation主题样式*/
@interface SDAppThemeConfigNavViewModel : NSObject@property (nonatomic, strong) NSString *backgroundColor;
@property (nonatomic, strong) NSString *backgroundImage;@property (nonatomic, strong) UIImage *t_backgroundImage;@property (nonatomic, strong) NSString *btnImageColor;
@property (nonatomic, strong) NSString *btnTitleColor;
@property (nonatomic, strong) NSString *navTitleColor;@property (nonatomic, strong) NSString *showLine;
@property (nonatomic, strong) NSString *lineColor;@end/**单个tab按钮样式*/
@interface SDAppThemeConfigTabItemViewModel : NSObject@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *titleColor;
@property (nonatomic, strong) NSString *selectedTitleColor;
@property (nonatomic, strong) NSString *icon;
@property (nonatomic, strong) NSString *selectedIcon;@property (nonatomic, strong) UIImage *t_icon;
@property (nonatomic, strong) UIImage *t_selectedIcon;@end/**tabbar样式*/
@interface SDAppThemeConfigTabViewModel : NSObject@property (nonatomic, strong) NSString *backgroundColor;
@property (nonatomic, strong) NSString *backgroundImage;
@property (nonatomic, strong) NSString *showLine;
@property (nonatomic, strong) NSString *lineColor;
@property (nonatomic, strong) NSString *badgeBgColor;@property (nonatomic, strong) UIImage *t_backgroundImage;@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *lianlian;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *guangguang;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *message;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *shop;
@property (nonatomic, strong) SDAppThemeConfigTabItemViewModel *mine;@end/**将本地的主题config.json转成viewmodel*/
@interface SDAppThemeConfigViewModel : NSObject@property (nonatomic, strong) NSString *globalColor;
@property (nonatomic, strong) NSString *globalImage;
@property (nonatomic, strong) SDAppThemeConfigNavViewModel *navigation;
@property (nonatomic, strong) SDAppThemeConfigTabViewModel *tabbar;@property (nonatomic, strong) UIImage *t_globalImage;+ (SDAppThemeConfigViewModel *)themeViewModel:(NSString *)themeJson;+ (SDAppThemeConfigViewModel *)defautThemeViewModel;@end

SDAppThemeConfigViewModel.m

#import "SDAppThemeConfigViewModel.h"
#import <NSObject+YYModel.h>/**Navigation主题样式*/
@implementation SDAppThemeConfigNavViewModel@end/**单个tab按钮样式*/
@implementation SDAppThemeConfigTabItemViewModel@end/**tabbar样式*/
@implementation SDAppThemeConfigTabViewModel@end/**将本地的主题config.json转成viewmodel*/
@implementation SDAppThemeConfigViewModel+ (SDAppThemeConfigViewModel *)themeViewModel:(NSString *)themeJson {return [SDAppThemeConfigViewModel modelWithJSON:themeJson];
}+ (SDAppThemeConfigViewModel *)defautThemeViewModel {SDAppThemeConfigViewModel *viewModel = [[SDAppThemeConfigViewModel alloc] init];SDAppThemeConfigNavViewModel *navConfigViewModel = [[SDAppThemeConfigNavViewModel alloc] init];navConfigViewModel.backgroundColor = @"171013";navConfigViewModel.btnImageColor = @"ffffff";navConfigViewModel.btnTitleColor = @"ffffff";navConfigViewModel.navTitleColor = @"ffffff";viewModel.navigation = navConfigViewModel;return viewModel;
}@end
  • 主题配置序列化存储本地:SDAppThemeConfigDbManager

SDAppThemeConfigDbManager.h

#import <Foundation/Foundation.h>
#import "SDAppThemeManager.h"@interface SDAppThemeConfigDbManager : NSObject+ (id)shareInstance;- (SDAppThemeViewModel *)getAppThemeViewModelFromDb;- (void)saveAppThemeViewModelToDb:(SDAppThemeViewModel *)info;@end

SDAppThemeConfigDbManager.m

#import "SDAppThemeConfigDbManager.h"static NSString *appThemeConfigPath = @"sdAppThemeConfigPath";
static SDAppThemeConfigDbManager *instance = nil;@implementation SDAppThemeConfigDbManager+ (id)shareInstance
{static dispatch_once_t predicate;dispatch_once(&predicate,^{instance = [[self alloc] init];});return instance;
}- (NSString *)getAppThemeConfigPath
{NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentPath = [paths objectAtIndex:0];NSString *path = [documentPath stringByAppendingPathComponent:appThemeConfigPath];return path;
}- (SDAppThemeViewModel *)getAppThemeViewModelFromDb {NSString *dataFile = [self getAppThemeConfigPath];@try {SDAppThemeViewModel *viewModel = [NSKeyedUnarchiver unarchiveObjectWithFile:dataFile];if (viewModel) {return viewModel;}} @catch (NSException *e) {}return nil;
}- (void)saveAppThemeViewModelToDb:(SDAppThemeViewModel *)info {NSData *data = [NSKeyedArchiver archivedDataWithRootObject:info];NSString *dataFile = [self getAppThemeConfigPath];BOOL isSave = [data writeToFile:dataFile atomically:YES];if (isSave) {NSLog(@"存储成功");} else {NSLog(@"存储失败");}
}@end

至此,实现获取下载主题配置更切换主题的代码实现完成。

五、小结

iOS开发-实现获取下载主题配置更切换主题,主要是通过请求服务端配置的主题配置、下载主题、解压保存到本地。通知界面获取对应的图片及颜色等。

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/14560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

REST API的基础:HTTP

在本文中&#xff0c;我们将深入探讨万维网数据通信的基础 - HTTP。 什么是超文本&#xff1f; HTTP&#xff08;超文本传输协议&#xff09;的命名源于“超文本”。 那么&#xff0c;什么是超文本&#xff1f; 想象一下由超链接组成的文本、图像和视频的混合物。这些链接充当我…

Restful的详细介绍~

RESTFUL简介&#xff1a; Restful是我们看待服务器的一种方式&#xff0c;我们都知道Java一切皆对象&#xff0c;因此在Java中&#xff0c;我们可以将所有的内容都看成对象&#xff0c;而在这里&#xff0c;RESTFUL是我们看待服务器的一种方式&#xff0c;我们可将服务器中的所…

【C++】多态的实现及其底层原理

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 我的gitee&#xff1a;gitee仓库 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处。 文章目录 前言一、什么是多态&#xff1f;二、多态的构成条件2.1什么是虚函数&#xff1f;2.2虚函数的重写2…

pycharm 远程连接服务器并且debug, 支持torch.distributed.launch debug

未经允许&#xff0c;本文不得转载&#xff0c;vx&#xff1a;837007389 文章目录 step1&#xff1a;下载专业版本的pycharmstep2 配置自动同步文件夹&#xff0c;即远程的工程文件和本地同步2.1 Tools -> Deployment -> configuration2.2 设置同步文件夹2.3 同步服务器…

【深度学习】WaveMix: A Resource-efficient Neural Network for Image Analysis 论文

论文&#xff1a;https://arxiv.org/abs/2205.14375 代码&#xff1a;https://github.com/pranavphoenix/WaveMix 文章目录 ABSTRACTIntroductionBackground and Related WorksWaveMix Architectural FrameworkOverall architectureWaveMix block Experiments and ResultsTasks…

机器学习深度学习——Dropout

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——权重衰减 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮助 Drop…

centos7安装nginx

一、下载安装包 方式一&#xff1a;官网下载 到nginx官网下载 然后上传到linux 服务器 方式二: wget 下载 wget http://nginx.org/download/nginx-1.22.0.tar.gz二、安装nginx 先安装相关依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 创建…

使用vim-cmd工具给ESXi虚机定期打快照

VMware虚拟化 - 建设篇 第四章 使用vim-cmd工具给ESXi虚机定期打快照 VMware虚拟化 - 建设篇系列文章回顾使用vim-cmd工具给ESXi虚机定期打快照前言前提条件ESXi新增执行快照备份的sh脚本ESXi添加crond任务并使其生效ESXi指定部分虚拟机不执行定期快照(附加)虚拟机自定义属性…

ChatGPT有几个版本,哪个版本最强,如何选择适合自己的?

​ChatGPT就像内容生产界的瑞士军刀。它可以是数学导师、治疗师、职业顾问、编程助手&#xff0c;甚至是旅行指南。只要你知道如何让它做你想做的事&#xff0c;ChatGPT几乎可以提供你要的任何东西。 但重要的是&#xff0c;你知道哪个版本的ChatGPT最能满足你的需求吗&#x…

Windows 11 下 OpenFace 2.2.0 的安装

写在前面 最近需要做关于面部的东西&#xff0c;所以需要使用到OpenFace这个工具&#xff0c;本文仅用来记录本人安装过程以供后续复现&#xff0c;如果可以帮助到读者也是非常荣幸。 安装过程 不编译直接使用 这种方法可以直接从官方下载下来编译好的exe以及gui进行使用&a…

在 “小小容器” WasmEdge 里运行小小羊驼 llama 2

昨天&#xff0c;特斯拉前 AI 总监、OpenAI 联合创始人 Andrej Karpathy 开源了 llama2.c 。 只用 500 行纯 C 语言就能训练和推理 llama 2 模型的框架&#xff0c;没有任何繁杂的 python 依赖。这个项目一推出就受到大家的追捧&#xff0c;24 小时内 GitHub 收获 4000 颗星&am…

KY222 打印日期+KY111日期差值

一、KY222题目 二、代码 #include <climits> #include <iostream> using namespace std; class Date{public:Date(int year 1,int month 2,int day 3){_year year;_month month;_day day;}int GetDay(int year ,int month);void Define(int n);public:int _yea…

查看进程方式

目录 ps top uptime pstree ps 查看静态的进程统计信息 top 实时显示系统中各个进程的资源占用情况 第一行 top - 17:00:23 up 15 min, 1 user, load average: 1.05, 1.22, 0.98 17:00:23————当前时间 up 15 min————系统运行时间 1 user————当前登录用户数…

陪诊小程序软件|陪诊系统定制|医院陪诊小程序

开发一个陪诊小程序需要投入一定的费用&#xff0c;具体金额会因项目的复杂程度、功能需求和推广政策而有所差异在投入资金之前&#xff0c;建议进行市场调研和需求分析&#xff0c;制定出合理的预算&#xff0c;并选择专业的开发团队进行合作&#xff0c;那么开发陪诊小程序需…

2023大同首届信息技术产业峰会举行,共话数字经济新未来

7月28日&#xff0c;“聚势而强共领信创”2023大同首届信息技术产业峰会圆满举行。本次峰会由中共大同市委、大同市人民政府主办&#xff0c;中国高科技产业化研究会国际交流合作中心、山西省信创协会协办&#xff0c;中共大同市云冈区委、大同市云冈区人民政府、诚迈科技&…

密码学的一些常识

1&#xff0c;对称密码、公钥密码、消息认证、数字签名的对比 对称密码公钥密码发送者共享秘钥加密公钥加密接收者共享秘钥解密私钥解密秘钥配送问题存在不存在&#xff0c;但需要CA认证公钥机密性√√ 消息认证数字签名发送者共享秘钥计算MAC使用私钥对文本HASH值做签名接收者…

JavaScript学习 -- SM3算法基本原理

SM3算法是一种由国家密码管理局发布的哈希算法&#xff0c;被广泛用于数字签名和消息认证等应用中。在JavaScript中&#xff0c;我们可以使用第三方库来计算数据的SM3哈希值。本篇文章将介绍SM3算法的基本原理和相关技术&#xff0c;并提供一些实例来演示如何在JavaScript中使用…

DAY14_FilterListenerAjaxAxiosJsonfastjson综合案例-axios和html交互

目录 1 Filter1.1 Filter概述1.2 Filter快速入门1.2.1 开发步骤1.2.2 代码演示 1.3 Filter执行流程1.4 Filter拦截路径配置1.5 过滤器链1.5.1 概述1.5.2 代码演示1.5.3 问题 1.6 案例1.6.1 需求1.6.2 分析1.6.3 代码实现1.6.3.1 创建Filter1.6.3.2 编写逻辑代码1.6.3.3 测试并抛…

ERROR in unable to locate ‘***/public/**/*‘ glob

前提 自己搭了一个react项目的脚手架&#xff0c;npm包下载一切都很正常&#xff0c;启动的时候突然就报ERROR in unable to locate ***/public/**/* glob这个错误&#xff0c;根据百度分析了一下产生的原因&#xff1a;webpack配置文件中的CopyWebpackPlugin导致的 网上给出的…

【idea工具】idea工具,build的时候提示:程序包 com.xxx.xx不存在的错误

idea工具&#xff0c;build的时候提示:程序包 com.xxx.xx不存在的错误&#xff0c;如下图&#xff0c;折腾了好一会&#xff0c; 做了如下操作还是不行&#xff0c;idea工具编译的时候&#xff0c;还是提示 程序包不存在。 a. idea中&#xff0c;重新导入项目&#xff0c;也还…