iOSSpin(換膚)

凌浩雨發表於2018-01-22

MTSkinTools.h

#import <UIKit/UIKit.h>

//專門寫常量值的
// 以下的格式, 只是對常量的宣告
//extern: 代表其他類可以引用
extern NSString *const MTSkinToolLabelTextDayColor;
extern NSString *const MTSkinToolLabelBackgroundDayColor;
@interface MTSkinTools : NSObject
/** 返回對應的皮膚的影像*/
+ (UIImage *)imageWithImageName:(NSString *)imageName;
/** 儲存皮膚資訊*/
+ (void)saveSkinName:(NSString *)skinName;
/** 返回制定識別符號所對應的顏色*/
+ (UIColor *)colorWithName:(NSString *)name;
@end

MTSkinTools.m

#import "MTSkinTools.h"

//專門寫常量值的

// 以下的格式, 只是對常量的宣告
NSString *const MTSkinToolLabelTextDayColor = @"labelTextDayColor";
NSString *const MTSkinToolLabelBackgroundDayColor = @"labelBackgroundDayColor";

static NSString *_skinName;

//#1. 建立一個static的可變字典
static NSMutableDictionary *_colorDict;

@implementation MTSkinTools

/**
 保證程式碼只載入一次:
 1. 多執行緒 --> dispatchOnce
 2. 只呼叫一次的方法
 */

/** load方法, 只要標頭檔案參與了編譯就會呼叫此方法 */
+ (void)load
{
    NSLog(@"%s",__func__);
}

/** 類的例項建立時, 才會呼叫此方法*/
+ (void)initialize
{
    //1. 讀取偏好設定資訊 --> 訪問磁碟是耗效能的, 所以只需要載入一次即可
    _skinName = [[NSUserDefaults standardUserDefaults] objectForKey:@"skinName"];
    
    if (_skinName == nil) {
        _skinName = @"green";
    }
    
    //#2. 可變字典做初始化
    _colorDict = [NSMutableDictionary dictionary];
    
    //#3. 載入顏色plist
    [self loadColorDict];
}


/** 返回對應的皮膚的影像*/
+ (UIImage *)imageWithImageName:(NSString *)imageName
{
    //1. 拼接檔案路徑
    NSString *imageStr = [NSString stringWithFormat:@"skin/%@/%@",_skinName,imageName];
    
    //2. 返回一個指定的影像
    return [UIImage imageNamed:imageStr];
}

/** 儲存皮膚資訊*/
+ (void)saveSkinName:(NSString *)skinName
{
    
    //當皮膚讀取改變成一次之後, 那麼我們做皮膚切換儲存操作, 原來的_skinName
    
    //更改皮膚
    _skinName = skinName;
    
    // 當設定了不同皮膚時, 我們還需要將皮膚plist顏色資訊進行重新載入
    [self loadColorDict];
    
    //儲存皮膚
    [[NSUserDefaults standardUserDefaults] setObject:skinName forKey:@"skinName"];
    [[NSUserDefaults standardUserDefaults] synchronize];
}


/** 返回制定識別符號所對應的顏色*/
+ (UIColor *)colorWithName:(NSString *)name
{
    return _colorDict[name];
}

/** 初始化時需要呼叫一次, 來載入字典及轉換顏色*/
+ (void)loadColorDict
{
    //1. 獲取plist列表
    //2. 顏色轉換(255,0,0,1 --> UIColor物件)
    
    //1. plist只需要載入一次
    //2. 將轉換後的UIColor做儲存
    
    //1. 獲取plist路徑
    NSString *pathStr = [NSString stringWithFormat:@"skin/%@/SkinColors.plist",_skinName];
    
    NSString *path = [[NSBundle mainBundle] pathForResource:pathStr ofType:nil];
    
    //2. 獲取字典
    NSDictionary *colorDict = [NSDictionary dictionaryWithContentsOfFile:path];
    
    //3. 直接獲取所有顏色值將其轉換成UIColor物件
    [colorDict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull colorStr, BOOL * _Nonnull stop) {
        
        //4. 擷取字串
        NSArray *colorArr = [colorStr componentsSeparatedByString:@","];
        
        //5. 建立顏色賦值給快取字典
        CGFloat r = [colorArr[0] doubleValue];
        CGFloat g = [colorArr[1] doubleValue];
        CGFloat b = [colorArr[2] doubleValue];
        CGFloat a = [colorArr[3] doubleValue];
        
        //字典的裡面存的是轉換好的UIColor物件, 當設定切換皮膚後, 需要重新呼叫此方法, 進行_colorDict的更新
        _colorDict[key] = [UIColor colorWithRed:r / 255.0 green:g / 255.0 blue:b / 255.0 alpha:a];
    }];
}

@end

ViewController.m

#import "ViewController.h"
#import "MTSkinTools.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *faceView;
@property (weak, nonatomic) IBOutlet UIImageView *heartView;
@property (weak, nonatomic) IBOutlet UIImageView *rectView;

@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 啟動時載入皮膚
    [self changeSkinWithSkinName:nil];
}

- (IBAction)redClick:(id)sender {
    
    // 切換皮膚
    [self changeSkinWithSkinName:@"red"];
}

- (IBAction)greenClick:(id)sender {
    // 切換皮膚
    [self changeSkinWithSkinName:@"green"];
}

- (IBAction)blueClick:(id)sender {
    // 切換皮膚
    [self changeSkinWithSkinName:@"blue"];
}

- (IBAction)orangeClick:(id)sender {
    // 切換皮膚
    [self changeSkinWithSkinName:@"orange"];
}

//抽取公用方法
- (void)changeSkinWithSkinName:(NSString *)skinName
{
    // 判斷如果皮膚名稱傳了空, 那麼不用管儲存
    if (skinName != nil) {
        [MTSkinTools saveSkinName:skinName];
    }
    
    // 切換影像
    self.faceView.image = [MTSkinTools imageWithImageName:@"face"];
    self.heartView.image = [MTSkinTools imageWithImageName:@"heart"];
    self.rectView.image = [MTSkinTools imageWithImageName:@"rect"];
    
    // 切換文字顏色
    self.label.textColor = [MTSkinTools colorWithName:MTSkinToolLabelTextDayColor];
    
    // 切換背景顏色
    self.label.backgroundColor = [MTSkinTools colorWithName:MTSkinToolLabelBackgroundDayColor];
}

@end


相關文章