你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS開發之獲取系統相冊中的圖片與視頻教程(內帶url轉換)

iOS開發之獲取系統相冊中的圖片與視頻教程(內帶url轉換)

編輯:IOS開發綜合

好些天沒寫點東西了,最近公司要做新項目,有點小忙。不想我的堅持就此中斷,我把我前些天研究的東西拿出來給大家看看。

這次整理的是AssetsLibrary和PhotoKit的使用。本人處女座,有點強迫症,之前寫的項目裡用的是AssetsLibrary寫的調取相冊內的媒體文件,但是Xcode總是報警告錯誤,雖然能夠編譯並展示效果,但是十幾個警告錯誤掛在那,心裡總不是滋味,所以我就研究了一下AssetLibrary和PhotoKit。

在 iOS 8 出現之前,開發者只能使用 AssetsLibrary 框架來訪問設備的照片庫,這是一個有點跟不上 iOS 應用發展步伐以及代碼設計原則但確實強大的框架,考慮到 iOS7 仍占有不少的滲透率,因此 AssetsLibrary 也是本文重點介紹的部分。而在 iOS8 出現之後,蘋果提供了一個名為 PhotoKit 的框架,一個可以讓應用更好地與設備照片庫對接的框架。

一、AssetsLibrary 組成

AssetsLibrary 的組成比較符合照片庫本身的組成,照片庫中的完整照片庫對象、相冊、相片都能在 AssetsLibrary 中找到一一對應的組成,這使到 AssetsLibrary 的使用變得直觀而方便。想要了解AssetsLibrary得從它的類開始。

AssetsLibrary: 代表整個設備中的資源庫(照片庫),通過 AssetsLibrary 可以獲取和包括設備中的照片和視頻

  • ALAssetsGroup: 映射照片庫中的一個相冊,通過 ALAssetsGroup 可以獲取某個相冊的信息,相 冊下的資源,同時也可以對某個相冊添加資源。
  • ALAsset: 映射照片庫中的一個照片或視頻,通過 ALAsset 可以獲取某個照片或視頻的詳細信息, 或者保存照片和視頻。
  • ALAssetRepresentation: ALAssetRepresentation 是對 ALAsset 的封裝(但不是其子類),可以更方便地獲取 ALAsset 中的資源信息,每個 ALAsset 都有至少有一個 ALAssetRepresentation 對象,可以通過 defaultRepresentation 獲取。而例如使用系統相機應用拍攝的 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]; 
  }); 
} 


@但是:
按照上面方法直接取出來的路徑是無法傳輸的,必須自己轉化成NSData對象重新寫入沙盒路徑

   // 將原始圖片的URL轉化為NSData數據,寫入沙盒 
- (void)imageWithUrl:(NSURL *)url withFileName:(NSString *)fileName 
{ 
  // 進這個方法的時候也應該加判斷,如果已經轉化了的就不要調用這個方法了 
  // 如何判斷已經轉化了,通過是否存在文件路徑 
  ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; 
  // 創建存放原始圖的文件夾--->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轉化為NSData數據,寫入沙盒 
- (void)videoWithUrl:(NSURL *)url withFileName:(NSString *)fileName 
{ 
  // 解析一下,為什麼視頻不像圖片一樣一次性開辟本身大小的內存寫入? 
  // 想想,如果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繼續 
          } 
          // 釋放緩沖區,關閉文件 
          free(buffer); 
          buffer = NULL; 
          fclose(file); 
          file = NULL; 
        } 
      } failureBlock:nil]; 
    } 
  }); 
} 

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

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved