換膚-顏色換膚優(yōu)化 - (Obj-C)

上一篇文章中提到了顏色換膚,在UIImage中封裝了一個(gè)loadColorWithKey:的方法,每一次設(shè)置都會(huì)調(diào)用該方法,每次都從磁盤中讀取plist文件獲取色表中的配色方案,這樣比較消耗性能,并且每一次從磁盤讀取數(shù)據(jù)比較耗時(shí).在皮膚不變的情況下,不需要每一次都從磁盤獲取.
所以只需要做一個(gè)緩存處理,在第一次從磁盤讀取時(shí)存到內(nèi)存中,當(dāng)切換皮膚后再操作一次,重新從磁盤獲取就可以了

色表本質(zhì)是一個(gè)plist文件,里面是一個(gè)字典
字典(key:plist中的key value:色值NSString) -> 字典(key:不變 value:UIColor)

原本每次從沙盒讀取數(shù)據(jù)加載顏色的方法:

+ (UIColor *)loadColorWithKey:(NSString *)key{

    // 每個(gè)皮膚除了設(shè)置不同圖片外,通常還需要有一套對應(yīng)的配色方案,一般使用plist色表來保存方案,色表的命名規(guī)范: 控制器_視圖_屬性
    NSString *path = @"";
    if (isNight) {
        path = @"skin/night/color.plist";
    }else {
        path = @"skin/default/color.plist";
    }
    NSDictionary *colorDict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:nil]];
    
    // 根據(jù)傳入的key取出value
    NSString *colorString = colorDict[key];
    // 將得到的value(NSString*)分隔轉(zhuǎn)成一個(gè)數(shù)組
    NSArray *colorArr = [colorString componentsSeparatedByString:@","];
    
    CGFloat red = [colorArr[0] floatValue];
    CGFloat green = [colorArr[1] floatValue];
    CGFloat blue = [colorArr[2] floatValue];
    
    UIColor *color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0];
    
    return color;
}

聲明一個(gè)靜態(tài)全局變量

// 色表的緩存
static NSDictionary *colorCache;

將從沙盒獲取數(shù)據(jù)的方法再次封裝,將皮膚顏色存放到緩存中:

// 加載色表緩存  硬盤數(shù)據(jù)-->內(nèi)存數(shù)據(jù)
+ (void)loadColorCache{
    
    // 從plist中取出色表
    NSString *path = @"";
    if (isNight) {
        path = @"skin/night/color.plist";
    }else {
        path = @"skin/default/color.plist";
    }
    
    NSDictionary *colorDict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:nil]];
    
    // 創(chuàng)建可變字典  將字符串字典轉(zhuǎn)換成UIColor字典
    NSMutableDictionary *tempDict = [NSMutableDictionary dictionary];
    
    // 遍歷字符串字典
    [colorDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        // 根據(jù)傳入的key取出value
        // 將得到的value(NSString*)分隔轉(zhuǎn)成一個(gè)數(shù)組
        NSArray *colorArr = [obj componentsSeparatedByString:@","];
        
        CGFloat red = [colorArr[0] floatValue];
        CGFloat green = [colorArr[1] floatValue];
        CGFloat blue = [colorArr[2] floatValue];
        
        // 設(shè)置色表的內(nèi)存緩存 方便從內(nèi)存中取出對應(yīng)的顏色,避免每一次都從沙盒中取出色表(影響性能)
        // 內(nèi)存緩存 選型  字典(key:plist中的key  value:色值NSString) -> 字典(key:不變  value:UIColor)
        UIColor *color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0];
        
        // 存到臨時(shí)可變字典中
        [tempDict setObject:color forKey:key];
        
    }];
    
    // 存到緩存
    colorCache = tempDict.copy;

    
}

原本的加載顏色的方法,只需要從內(nèi)存中根據(jù)key獲取緩存的顏色即可

+ (UIColor *)loadColorWithKey:(NSString *)key{

    // 從內(nèi)存中剛?cè)〕鰧?yīng)的顏色
    return colorCache[key];
}

同時(shí)在初始化和本地化時(shí)分別調(diào)用一次即可,外界使用不受影響,不需要變動(dòng)

完整代碼

#import "UIImage+JSSkin.h"
#import <objc/runtime.h>

@implementation UIImage (JSSkin)

// 夜間模式標(biāo)識(靜態(tài)全局變量)
static bool isNight;
// 色表的緩存
static NSDictionary *colorCache;

+ (void)load{

    // 獲取偏好設(shè)置中的皮膚模式
    isNight = [[NSUserDefaults standardUserDefaults] boolForKey:@"isNight"];
    
    // 使用運(yùn)行時(shí)機(jī)制交換方法 一旦交換,在App整個(gè)生命周期都會(huì)交換
    // 1. 獲取對應(yīng)交換的方法
    Method method1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
    Method method2 = class_getClassMethod([UIImage class], @selector(jsImageNamed:));
    // 2. 交換方法
    method_exchangeImplementations(method1, method2);
    
    // 加載色表緩存
    [self loadColorCache];
}

+ (UIColor *)loadColorWithKey:(NSString *)key{
    // 從內(nèi)存中剛?cè)〕鰧?yīng)的顏色
    return colorCache[key];
}

// 加載色表緩存  硬盤數(shù)據(jù)-->內(nèi)存數(shù)據(jù)
+ (void)loadColorCache{
    
    // 從plist中取出色表
    NSString *path = @"";
    if (isNight) {
        path = @"skin/night/color.plist";
    }else {
        path = @"skin/default/color.plist";
    }
    
    NSDictionary *colorDict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:path ofType:nil]];
    
    // 創(chuàng)建可變字典  將字符串字典轉(zhuǎn)換成UIColor字典
    NSMutableDictionary *tempDict = [NSMutableDictionary dictionary];
    
    // 遍歷字符串字典
    [colorDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        // 根據(jù)傳入的key取出value
        // 將得到的value(NSString*)分隔轉(zhuǎn)成一個(gè)數(shù)組
        NSArray *colorArr = [obj componentsSeparatedByString:@","];
        
        CGFloat red = [colorArr[0] floatValue];
        CGFloat green = [colorArr[1] floatValue];
        CGFloat blue = [colorArr[2] floatValue];
        
        // 設(shè)置色表的內(nèi)存緩存 方便從內(nèi)存中取出對應(yīng)的顏色,避免每一次都從沙盒中取出色表(影響性能)
        // 內(nèi)存緩存 選型  字典(key:plist中的key  value:色值NSString) -> 字典(key:不變  value:UIColor)
        UIColor *color = [UIColor colorWithRed:red / 255.0 green:green / 255.0 blue:blue / 255.0 alpha:1.0];
        
        // 存到臨時(shí)可變字典中
        [tempDict setObject:color forKey:key];
        
    }];
    
    // 存到緩存
    colorCache = tempDict.copy;

    
}

// 自定義方法,根據(jù)當(dāng)前皮膚設(shè)置圖片
+ (UIImage *)jsImageNamed:(NSString *)name{
    
    if (isNight) { // 夜間模式
        
        name = [NSString stringWithFormat:@"%@_night",name];
    }
    
    return [UIImage jsImageNamed:name];
}

+ (void)saveSkinModeWithNight:(BOOL)night{
    
    // 賦值,記錄當(dāng)前皮膚狀態(tài)
    isNight = night;
    
    // 本地記錄狀態(tài)(偏好設(shè)置)
    [[NSUserDefaults standardUserDefaults] setBool:isNight forKey:@"isNight"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    // 加載色表緩存
    [self loadColorCache];
}

+ (BOOL)isNight{
    
    // 返回當(dāng)前皮膚狀態(tài)
    return isNight;
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1.自定義控件 a.繼承某個(gè)控件 b.重寫initWithFrame方法可以設(shè)置一些它的屬性 c.在layouts...
    圍繞的城閱讀 3,484評論 2 4
  • 1.1 談一談GCD和NSOperation的區(qū)別? 首先二者都是多線程相關(guān)的概念,當(dāng)然在使用中也是根據(jù)不同情境進(jìn)...
    John_LS閱讀 1,343評論 0 12
  • 圖片下載的這些回調(diào)信息存儲(chǔ)在SDWebImageDownloader類的URLOperations屬性中,該屬性是...
    怎樣m閱讀 2,428評論 0 1
  • 緩存的四種方式?各自應(yīng)用的場景? 緩存本質(zhì)將請求到的數(shù)據(jù)存儲(chǔ)到本地,將數(shù)據(jù)顯示到UI界面前先詢問本地?cái)?shù)據(jù)庫是否已經(jīng)...
    Carden閱讀 865評論 0 1
  • Objective-C學(xué)習(xí)Foundation構(gòu)架秘籍 第1章Objective-C學(xué)習(xí)環(huán)境準(zhǔn)備 1.1Objec...
    NieFeng1024閱讀 386評論 0 1