iOS開發(fā)之獲取系統(tǒng)相冊中的圖片與視頻教程(內(nèi)帶url轉(zhuǎn)換)
好些天沒寫點東西了,最近公司要做新項目,有點小忙。不想我的堅持就此中斷,我把我前些天研究的東西拿出來給大家看看。
這次整理的是AssetsLibrary和PhotoKit的使用。本人處女座,有點強迫癥,之前寫的項目里用的是AssetsLibrary寫的調(diào)取相冊內(nèi)的媒體文件,但是Xcode總是報警告錯誤,雖然能夠編譯并展示效果,但是十幾個警告錯誤掛在那,心里總不是滋味,所以我就研究了一下AssetLibrary和PhotoKit。
在 iOS 8 出現(xiàn)之前,開發(fā)者只能使用 AssetsLibrary 框架來訪問設備的照片庫,這是一個有點跟不上 iOS 應用發(fā)展步伐以及代碼設計原則但確實強大的框架,考慮到 iOS7 仍占有不少的滲透率,因此 AssetsLibrary 也是本文重點介紹的部分。而在 iOS8 出現(xiàn)之后,蘋果提供了一個名為 PhotoKit 的框架,一個可以讓應用更好地與設備照片庫對接的框架。
一、AssetsLibrary 組成
AssetsLibrary 的組成比較符合照片庫本身的組成,照片庫中的完整照片庫對象、相冊、相片都能在 AssetsLibrary 中找到一一對應的組成,這使到 AssetsLibrary 的使用變得直觀而方便。想要了解AssetsLibrary得從它的類開始。
AssetsLibrary: 代表整個設備中的資源庫(照片庫),通過 AssetsLibrary 可以獲取和包括設備中的照片和視頻
- ALAssetsGroup: 映射照片庫中的一個相冊,通過 ALAssetsGroup 可以獲取某個相冊的信息,相 冊下的資源,同時也可以對某個相冊添加資源。
- ALAsset: 映射照片庫中的一個照片或視頻,通過 ALAsset 可以獲取某個照片或視頻的詳細信息, 或者保存照片和視頻。
- ALAssetRepresentation: ALAssetRepresentation 是對 ALAsset 的封裝(但不是其子類),可以更方便地獲取 ALAsset 中的資源信息,每個 ALAsset 都有至少有一個 ALAssetRepresentation 對象,可以通過 defaultRepresentation 獲取。而例如使用系統(tǒng)相機應用拍攝的 RAW + JPEG 照片,則會有兩個 ALAssetRepresentation,一個封裝了照片的 RAW 信息,另一個則封裝了照片的 JPEG 信息。
@話不多說,直接上代碼
#import <AssetsLibrary/AssetsLibrary.h> // 必須導入
// 照片原圖路徑
#define KOriginalPhotoImagePath \
[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"OriginalPhotoImages"]
// 視頻URL路徑
#define KVideoUrlPath \
[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"VideoURL"]
// caches路徑
#define KCachesPath \
[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0]
// MainViewController
@interface MTHMainViewController ()
@property (nonatomic,strong) MTHNextViewController *nextVC;
@property (nonatomic,strong) NSMutableArray *groupArrays;
@property (nonatomic,strong) UIImageView *litimgView;
@end
@implementation MTHMainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = @"Demo";
self.view.backgroundColor = [UIColor clearColor];
// 初始化
self.groupArrays = [NSMutableArray array];
// 測試BarItem
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"測試" style:UIBarButtonItemStylePlain target:self action:@selector(testRun)];
// 測試手勢
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didClickPanGestureRecognizer:)];
[self.navigationController.view addGestureRecognizer:panRecognizer];
// 圖片或者視頻的縮略圖顯示
self.litimgView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 200, 120, 120)];
[self.view addSubview:_litimgView];
}
- (void)testRun
{
__weak MTHMainViewController *weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ALAssetsLibraryGroupsEnumerationResultsBlock listGroupBlock = ^(ALAssetsGroup *group, BOOLBOOL *stop) {
if (group != nil) {
[weakSelf.groupArrays addObject:group];
} else {
[weakSelf.groupArrays enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOLBOOL *stop) {
[obj enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOLBOOL *stop) {
if ([result thumbnail] != nil) {
// 照片
if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]){
NSDate *date= [result valueForProperty:ALAssetPropertyDate];
UIImage *image = [UIImage imageWithCGImage:[result thumbnail]];
NSString *fileName = [[result defaultRepresentation] filename];
NSURL *url = [[result defaultRepresentation] url];
int64_t fileSize = [[result defaultRepresentation] size];
NSLog(@"date = %@",date);
NSLog(@"fileName = %@",fileName);
NSLog(@"url = %@",url);
NSLog(@"fileSize = %lld",fileSize);
// UI的更新記得放在主線程,要不然等子線程排隊過來都不知道什么年代了,會很慢的
dispatch_async(dispatch_get_main_queue(), ^{
self.litimgView.image = image;
});
}
// 視頻
else if ([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo] ){
// 和圖片方法類似
}
}
}];
}];
}
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error)
{
NSString *errorMessage = nil;
switch ([error code]) {
case ALAssetsLibraryAccessUserDeniedError:
case ALAssetsLibraryAccessGloballyDeniedError:
errorMessage = @"用戶拒絕訪問相冊,請在<隱私>中開啟";
break;
default:
errorMessage = @"Reason unknown.";
break;
}
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"錯誤,無法訪問!"
message:errorMessage
delegate:self
cancelButtonTitle:@"確定"
otherButtonTitles:nil, nil nil];
[alertView show];
});
};
ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll
usingBlock:listGroupBlock failureBlock:failureBlock];
});
}

@但是:
按照上面方法直接取出來的路徑是無法傳輸?shù)?必須自己轉(zhuǎn)化成NSData對象重新寫入沙盒路徑
// 將原始圖片的URL轉(zhuǎn)化為NSData數(shù)據(jù),寫入沙盒
- (void)imageWithUrl:(NSURL *)url withFileName:(NSString *)fileName
{
// 進這個方法的時候也應該加判斷,如果已經(jīng)轉(zhuǎn)化了的就不要調(diào)用這個方法了
// 如何判斷已經(jīng)轉(zhuǎn)化了,通過是否存在文件路徑
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
// 創(chuàng)建存放原始圖的文件夾--->OriginalPhotoImages
NSFileManager * fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:KOriginalPhotoImagePath]) {
[fileManager createDirectoryAtPath:KOriginalPhotoImagePath withIntermediateDirectories:YES attributes:nil error:nil];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (url) {
// 主要方法
[assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *rep = [asset defaultRepresentation];
Byte *buffer = (Byte*)malloc((unsigned long)rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:((unsigned long)rep.size) error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
NSString * imagePath = [KOriginalPhotoImagePath stringByAppendingPathComponent:fileName];
[data writeToFile:imagePath atomically:YES];
} failureBlock:nil];
}
});
}
// 將原始視頻的URL轉(zhuǎn)化為NSData數(shù)據(jù),寫入沙盒
- (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName
{
// 解析一下,為什么視頻不像圖片一樣一次性開辟本身大小的內(nèi)存寫入?
// 想想,如果1個視頻有1G多,難道直接開辟1G多的空間大小來寫?
ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (url) {
[assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
ALAssetRepresentation *rep = [asset defaultRepresentation];
NSString * videoPath = [KCachesPath stringByAppendingPathComponent:fileName];
char constconst *cvideoPath = [videoPath UTF8String];
FILEFILE *file = fopen(cvideoPath, "a+");
if (file) {
const int bufferSize = 11024 * 1024;
// 初始化一個1M的buffer
Byte *buffer = (Byte*)malloc(bufferSize);
NSUInteger read = 0, offset = 0, written = 0;
NSError* err = nil;
if (rep.size != 0)
{
do {
read = [rep getBytes:buffer fromOffset:offset length:bufferSize error:&err];
written = fwrite(buffer, sizeof(char), read, file);
offset += read;
} while (read != 0 && !err);//沒到結尾,沒出錯,ok繼續(xù)
}
// 釋放緩沖區(qū),關閉文件
free(buffer);
buffer = NULL;
fclose(file);
file = NULL;
}
} failureBlock:nil];
}
});
}
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
詳解Obejective-C中將JSON數(shù)據(jù)轉(zhuǎn)為模型的方法
這篇文章主要介紹了Obejective-C中JSON數(shù)據(jù)轉(zhuǎn)為模型的方法,同時介紹了使用jastor庫的方法,需要的朋友可以參考下2016-03-03
ios通過SDWebImage實現(xiàn)圖片加載時的漸變效果
本篇文章主要介紹了ios通過SDWebImage實現(xiàn)圖片加載時的漸變效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
iOS App使用SQLite之句柄的定義及數(shù)據(jù)庫的基本操作
SQLite中在定義過句柄之后就可以指向數(shù)據(jù)庫,從而利用iOS應用程序進行打開或關閉等各種操作,這里我們就來看一下iOS App使用SQLite之句柄的定義及數(shù)據(jù)庫的基本操作2016-06-06
iOS通過UIDocumentInteractionController實現(xiàn)應用間傳文件
這篇文章主要為大家介紹了iOS通過UIDocumentInteractionController實現(xiàn)應用間傳文件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01

