實現iOS圖片等資源文件的熱更新化(二):自定義的動態 imageNamed

這篇文章,要解決的是,使用一個自定義的 imageNamed 函數來替代系統的 imageNamed 函數.內部邏輯,將貫穿對比論證 關於"合適"的圖片的定義.對iOS加載圖片的規則不是很熟悉的童鞋,能夠着重看這篇.react

不一樣後綴圖片加載的優先級

  • iPhone 7 plus(iOS10.0): sample@3x.png > sample@2x.png > sample~iphone.png >sample.png 其餘後綴的圖片老是不被加載.ios

  • iPad Pro 12.9 inch(iOS10.0): sample@2x.png > sample~ipad.png > sample.png 其餘後綴的圖片老是不被加載.git

不一樣後綴的圖片 iPhone 7 plus(iOS10.0) iPad Pro 12.9 inch(iOS10.0)
sample.png 7 8
sample@2x.png 9 10
sample@3x.png 10 0
sample~iphone.png 8 0
sample~iphone@2x.png 0 0
sample~iphone@3x.png 0 0
sample~ipad.png 0 9
sample~ipad@2x.png 0 0

可使用同名不一樣內容的圖片來對比觀察.優先級從高到低.優先級較高的優先被加載,優先級爲0的永遠不會被加載.僅以iPhone 7 plus 和 iPad Pro爲例分析,其餘狀況可自行.所用驗證版本爲iOS10,將來不一樣機型手機和系統可能會有差別.github

想本身動手試一下的,能夠下載示例: https://github.com/ios122/ios_assets_hot_update/raw/master/res/ios_assets_hot_update_2.zip 很小,只有100多K.編譯,我此時用的是 Xcode 8.react-native

使用bundle包放置圖片等資源文件

使用bundle包放置圖片等資源文件

資源把到一個bundle包中,便於保留資源的目錄結構,也方便總體管理與替換.iOS中的bundle包,就一個一個特殊的以.bunle結尾的文件夾.示例中,我使用的是main.bundle.另外,關於bundle保留資源目錄結構這個特色,是react-native中很依賴的一個特性,之後你的項目中或許也會須要.若是單單只是從原有 Images.xcassets 遷移代碼的話,此處都放於同一層級便可.iphone

使用 imageWithContentsOfFile: 加載圖片

把圖片放到資源文件夾main.bundle後,再加載圖片,能夠參考下面的代碼,這樣作的額外的好處就是能夠適當減少圖片加載的內存佔用問題:函數

NSString * bundlePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:@"main.bundle"];
NSBundle * mainBundle = [NSBundle bundleWithPath:bundlePath];
NSString * imgPath = [mainBundle pathForResource:@"sample" ofType:@"png"];
self.sampleImageView.image = [UIImage imageWithContentsOfFile: imgPath];

使iPhone @3x 與iPad @2x 共用同一張圖片

首先是須要顯示加載 @3x 的圖片:url

NSString * imgPath = [mainBundle pathForResource:@"sample@3x" ofType:@"png"];

此時代碼,在iPhone 7 / iPhone 7 plus/ iPad Pro,都能顯示圖片,直接輸出圖片自己的尺寸都爲 原圖尺寸的 1/3.3d

NSLog(@"加載後的圖片尺寸:%@",[NSValue valueWithCGSize:self.sampleImageView.image.size]);

可是,此處有一個問題.@3x老是被解讀爲三倍圖,在iPhone上,正是咱們須要的尺寸,可是在iPad上,尺寸就有些偏小了.咱們在iPad上,一般老是須要將此張圖按照@2x圖來顯示.這是一個規律!作過iPhone和iPad通用圖標尺寸適配的童鞋,應該早就注意到了.code

因此,如今要解決的關鍵技術問題是:如何把 @3x圖,在iPad上按照@2x圖來解讀?相對完整代碼以下,最終輸出的圖片尺寸在iPhone上爲原始尺寸的1/3,在iPad上爲原始尺寸的1/2,正是咱們須要的:

NSString * bundlePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent:@"main.bundle"];
 NSBundle * mainBundle = [NSBundle bundleWithPath:bundlePath];
 NSString * imgPath = [mainBundle pathForResource:@"sample@3x" ofType:@"png"];

 UIImage * image;
 static NSString * model;

 if (!model) {
     model = [[UIDevice currentDevice]model];
 }

 if ([model isEqualToString:@"iPad"]) {
     NSData *imageData = [NSData dataWithContentsOfFile: imgPath];
     image = [UIImage imageWithData:imageData scale:2.0];
 }else{
     image = [UIImage imageWithContentsOfFile: imgPath];
 }

 self.sampleImageView.image = image;

 NSLog(@"加載後的圖片尺寸:%@",[NSValue valueWithCGSize:self.sampleImageView.image.size]);

封裝爲類目(category),實現自定義的 imageNamed

此處實現了一個簡單夠用的類目方法,支持從指定bundle讀取指定名字的圖片:

#import "UIImage+imageNamed_bundle_.h"

@implementation UIImage (imageNamed_bundle_)
+ (UIImage *)imageNamed:(NSString *)imgName bundle:(NSString *)bundleName
{
    bundleName = [NSString stringWithFormat:@"%@.bundle",bundleName];
    imgName = [NSString stringWithFormat:@"%@@3x",imgName];

    NSString * bundlePath = [[NSBundle mainBundle].resourcePath stringByAppendingPathComponent: bundleName];
    NSBundle * mainBundle = [NSBundle bundleWithPath:bundlePath];
    NSString * imgPath = [mainBundle pathForResource:imgName ofType:@"png"];

    UIImage * image;
    static NSString * model;

    if (!model) {
        model = [[UIDevice currentDevice]model];
    }

    if ([model isEqualToString:@"iPad"]) {
        NSData *imageData = [NSData dataWithContentsOfFile: imgPath];
        image = [UIImage imageWithData:imageData scale:2.0];
    }else{
        image = [UIImage imageWithContentsOfFile: imgPath];
    }
    return  image;
}
@end

藉助類目,原來的調用,能夠簡化爲:

UIImage * image = [UIImage imageNamed:@"sample" bundle:@"main"];
self.sampleImageView.image = image;

也支持有層級結構的圖片資源的讀取呦:

UIImage * image = [UIImage imageNamed:@"sub/sample" bundle:@"main"];
self.sampleImageView.image = image;

參考連接

系列專屬 github 項目主頁

https://github.com/ios122/ios_assets_hot_update

相關文章
相關標籤/搜索