1. 程式人生 > 程式設計 >IOS 圖片存放3種方式的實現

IOS 圖片存放3種方式的實現

Image.xcassets

  • 建立 .xcassets,以 Image Set 形式管理圖片,新增圖片後會生成對應的 content.json 檔案
  • 加入 @2x 和 @3x 等倍圖後,打包後以 Assets.car 的形式存在,
  • 使用 [UIImage imageNamed:@"xxx"] 方式讀取圖片,可以使用圖片快取 —— 相當於建立了一個 key-value的字典,key 為圖片名,value 為圖片物件。建立圖片物件後,該物件被加入到 NSCache 中(解碼後的 Image Buffer),直到收到記憶體警告的時候,才會釋放不在使用的圖片物件。 因此,對於需要在多處顯示的圖片,其對應的 UIImage 物件只會被建立一次(不考慮記憶體警告時的回收),減少記憶體消耗。

圖片直接加入工程中作為Resource

讀取方式:建立圖片 Resource 資料夾,直接將圖片加入到工程中,使用如下方式讀取圖片

NSString *path = [NSBundle.mainBundle pathForResource:@"xxx" type:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:path];

特性:在 Resource 的圖片管理方式中,所有的圖片建立都是通過讀取檔案資料得到的,讀取一次檔案資料就會產生一次 NSData 以及產生一個 UIImage。 當圖片建立好後銷燬對應的 NSData,當 UIImage 的引用計數器變為 0 的時候自動銷燬 UIImage,這樣的話就可以保證圖片不會長期地存在在記憶體中

使用場景:由於這種方法的特性,所以 Resource 的方法一般用在圖片資料很大,圖片一般不需要多次使用的情況,比如說引導頁背景(圖片全屏)

優勢:圖片不會長期儲存在記憶體當中,所以不會有很多的記憶體浪費。同時,大圖一般不會長期使用,而且大圖佔用記憶體一般比小圖多了好多倍,所以在減少大圖的記憶體佔用中,Resource 做的非常好

使用Bundle檔案

  • Bundle 即資原始檔包,將許多圖片,XIB,文字檔案組織在一起,打包成一個 Bundle 檔案,方便在其他專案中引用包內的資源。
  • Bundle 檔案是靜態的,不參與專案的編譯,Bundle 包中不能包含可執行的檔案,它僅僅是作為資源,被解析成為特定的二進位制資料。
  • 優勢:Bundle 中檔案不參與專案編譯,不影響App包的大小(可用於App的瘦身); 使用 bundle 方式方便對檔案進行管理,方便在其他專案中引用包內的資源。
  • 使用場景:較大的圖片,或者使用頻率較低的圖片
  • 讀取方式:使用 imageWithContentsOfFile 進行讀取,如下方法1;也可以對 UIImage 進行擴充套件,如下方法2

使用 imageWithContentsOfFile 讀取

/// BSKDefine.h

// bundle path
#define STBundle_Name @"SafeToolResource.bundle"
#define STBundle_Path [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:STBundle_Name]
#define STBundle [NSBundle bundleWithPath:STBundle_Path]
/// usage

#import "BSKDefine.h"
UIImageView * headerBgImgView = [[UIImageView alloc] init];
headerBgImgView.image = [UIImage imageWithContentsOfFile:[SecKill_BUNDLE pathForResource:@"xxxx" ofType:@"png"]];

對 UIImage 進行擴充套件,建立 UIImage+BSKResources 類

/// UIImage+BSKResources.h

NS_ASSUME_NONNULL_BEGIN

@interface UIImage (BSKResources)

+ (UIImage *)bskImageNamed:(NSString *)imageName InBundleName:(NSString *)bundleName;

@end

NS_ASSUME_NONNULL_END
/// UIImage+BSKResources.m

#import "UIImage+BSKResources.h"

@implementation UIImage (BSKResources)

+ (UIImage *)bskImageNamed:(NSString *)imageName InBundleName:(NSString *)bundleName
{
  NSString *resourcePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:bundleName];
  NSBundle *resourceBundle = [NSBundle bundleWithPath:resourcePath];
  return [UIImage imageNamed:imageName inBundle:resourceBundle compatibleWithTraitCollection:nil];
}
@end

/// usage

#import "UIImage+BSKResources.h"

UIImageView * headerBgImgView = [[UIImageView alloc] init];
headerBgImgView.image = [UIImage bskImageNamed:@"xxx" InBundleName:@"BSKResources.bundle"]];

Bundle 和 xcassets 區別

  • xcassets 裡面的圖片,只能通過 imageNamed 載入。Bundle 還可以通過 imageWithContentsOfFile 等方式載入
  • xcassets 裡的 2x 和 3x,會根據具體裝置分發,不會同時包含(App Slicing),而 Bundle 會都包含
  • xcassets 內,可以對圖片進行 Slicing,即裁剪和拉伸,Bundle 不支援
  • Bundle 內支援多語言,xcassets 不支援
  • 此外,使用 imageNamed 建立的 UIImage,會立即被加入到 NSCache 中(解碼後的 Image Buffer),直到收到記憶體警告的時候,才會釋放不在使用的 UIImage;而使用 imageWithContentsOfFile 建立的物件,每次都會重新申請記憶體,相同圖片不會快取。因此,建議常用的、較小的圖,放在 xcassets 內管理,而大圖、使用頻率較低的圖,應該放在 Bundle 內管理

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。