iOS 11中,如果你是iPhone 7及以上設備,系統用了新的格式來存儲視頻和圖片,
如果你的App支持上傳圖片原文件,那么很可能會有圖片無法顯示的問題。
讀取圖片原文件的代碼一般是下面這樣的,傳到后臺之后得到一個url,webview和UIImage是無法顯示的。
[[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if (imageData) {
}
}];
當我們講適配的時候,往往比較多地關注UI的適配,容易忽略一些看不見的東西。
識別HEIF
識別HEIF文件的方法和識別GIF一樣,對比文件UTI(uniformTypeIdentifier)
__block BOOL isHEIF = NO;
if (iOSVersionGreaterThanOrEqualTo(@"9.0")) {
NSArray *resourceList = [PHAssetResource assetResourcesForAsset:phAsset];
[resourceList enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHAssetResource *resource = obj;
NSString *UTI = resource.uniformTypeIdentifier;
if ([UTI isEqualToString:@"public.heif"] || [UTI isEqualToString:@"public.heic"]) {
isHEIF = YES;
*stop = YES;
}
}];
} else {
NSString *UTI = [phAsset valueForKey:@"uniformTypeIdentifier"];
isHEIF = [UTI isEqualToString:@"public.heif"] || [UTI isEqualToString:@"public.heic"];
}
下面這個方法不準確
[[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
//這個dataUTI只是根據文件擴展名傳過來的,不準確
}];
轉換
方法一:有損
既然我們可以前置識別了,那么針對HEIF可以選擇通過requestImageDataForAsset:phAsset
獲取到UIImage,再用UIImageJPEGRepresentation
轉為NSData,不過轉為UIImage之后,圖片的其他信息(Exif、GPS等)就丟失了。
方法二:無損
[[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if (isHEIF) {
CIImage *ciImage = [CIImage imageWithData:imageData];
CIContext *context = [CIContext context];
NSData *jpgData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{}];
} else {
}
}];
方法三:無損
if (isHEIF) {
[phAsset requestContentEditingInputWithOptions:nil completionHandler:^(PHContentEditingInput * _Nullable contentEditingInput, NSDictionary * _Nonnull info) {
if (contentEditingInput.fullSizeImageURL) {
CIImage *ciImage = [CIImage imageWithContentsOfURL:contentEditingInput.fullSizeImageURL];
CIContext *context = [CIContext context];
NSData *jpgData = [context JPEGRepresentationOfImage:ciImage colorSpace:ciImage.colorSpace options:@{}];
}
}];
}
UIImage加載HEIF
CIImage *ciImage = [CIImage imageWithContentsOfURL:url];
imageView.image = [UIImage imageWithCIImage:ciImage];
這個方法有點慢,也可以使用CGImageSourceCreateWithURL和CGImageSourceCreateImageAtIndex加載