ios開發多選照片實現


#import "ViewController.h"
#import <Photos/Photos.h>

@interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (IBAction)selectImage {
    [self getThumbnailImages];
}

/**
 *  獲得所有相簿的原圖
 */
- (void)getOriginalImages
{
    // 獲得所有的自定義相簿
    PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍歷所有的自定義相簿
    for (PHAssetCollection *assetCollection in assetCollections) {
        [self enumerateAssetsInAssetCollection:assetCollection original:YES];
    }
    
    // 獲得相機膠卷
    PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
    [self enumerateAssetsInAssetCollection:cameraRoll original:YES];
}

/**
 *  獲得所有相簿中的縮略圖
 */
- (void)getThumbnailImages
{
    // 獲得所有的自定義相簿
    PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    // 遍歷所有的自定義相簿
    for (PHAssetCollection *assetCollection in assetCollections) {
        [self enumerateAssetsInAssetCollection:assetCollection original:NO];
    }
    
    // 獲得相機膠卷
    PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
    [self enumerateAssetsInAssetCollection:cameraRoll original:NO];
}

/**
 *  遍歷相簿中的所有圖片
 *
 *  @param assetCollection 相簿
 *  @param original        是否要原圖
 */
- (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollection original:(BOOL)original
{
    NSLog(@"相簿名:%@", assetCollection.localizedTitle);
    
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    // 同步獲得圖片, 只會返回1張圖片
    options.synchronous = YES;

    // 獲得某個相簿中的所有PHAsset對象
    PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    for (PHAsset *asset in assets) {
        // 是否要原圖
        CGSize size = original ? CGSizeMake(asset.pixelWidth, asset.pixelHeight) : CGSizeZero;
        
        // 從asset中獲得圖片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            NSLog(@"%@", result);
        }];
    }
}

/**
 *  獲得相機膠卷中的所有圖片
 */
- (void)getImagesFromCameraRoll
{
    // 獲得相機膠卷中的所有圖片
    PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithOptions:nil];
    
    __block int count = 0;
    
    for (PHAsset *asset in assets) {
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(asset.pixelWidth, asset.pixelHeight) contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
            NSLog(@"%@ - %zd", result, count++);
        }];
    }
}

/**
 *  利用UIImagePickerController挑選圖片
 */
- (void)getImageFromIpc
{
    // UIImagePickerController : 可以從系統自帶的App(照片\相機)中獲得圖片

    // 判斷相冊是否可以打開
    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;

    UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
    // 打開照片應用(顯示所有相簿)
    ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    // 打開照片應用(只顯示"時刻"這個相簿)
    // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    // 照相機
    // ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
    ipc.delegate = self;
    [self presentViewController:ipc animated:YES completion:nil];
}

#pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    // 銷毀控制器
    [picker dismissViewControllerAnimated:YES completion:nil];

    // 設置圖片
    self.imageView.image = info[UIImagePickerControllerOriginalImage];
}

@end

總結:1:從相冊中選取照片可以利用UIImagePickerController,前提是必須遵守兩個協議:

<UIImagePickerControllerDelegate, UINavigationControllerDelegate>但是此種方法只能獲取到相冊中的一張照片。使用方法如下:1:可以先判斷其是否支持相機或是相冊,不支持直接return,不執行以下代碼 2:創建對象,設置代理,在設置sourceType(注意兩種類型的區別),彈出就用presentViewController可以彈出相冊,dissmiss返回到應用。實現代理方法獲取圖片:   self.imageView.image = info[UIImagePickerControllerOriginalImage];3:UIImagePickerController顯示中文界面:

1.Project-->Info-->Localizations添加Chinese

2.修改Target-->Info-->Localization native development region : China 

- (void)getImageFromIpc

{

    // UIImagePickerController : 可以從系統自帶的App(照片\相機)中獲得圖片

 

    // 判斷相冊是否可以打開

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;

 

    UIImagePickerController *ipc = [[UIImagePickerController alloc] init];

    // 打開照片應用(顯示所有相簿)

    ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    // 打開照片應用(只顯示"時刻"這個相簿)

    // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;

    // 照相機

    // ipc.sourceType = UIImagePickerControllerSourceTypeCamera;

    ipc.delegate = self;

    [self presentViewController:ipc animated:YES completion:nil];

}

 

#pragma mark - <UIImagePickerControllerDelegate>

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

{

    // 銷毀控制器

    [picker dismissViewControllerAnimated:YES completion:nil];

 

    // 設置圖片

    self.imageView.image = info[UIImagePickerControllerOriginalImage];

}

 2:若是想多選照片:1:可用系統框架:#import <Photos/Photos.h>  2:使用步驟:1:先獲得所有相簿,在獲得相簿膠卷  

PHAssetCollection

2:遍歷相簿數組,得到每一個相冊照片PHAsset,再利用PHAsset請求獲得每一張照片

3:若想做成系統相簿的樣式:1:此界面可采用九宮格搭建,或是采用collection搭建,建議用后者,因為后者可以有循環利用的機制,節省

內存

2:如下界面搭建:可以監聽每張圖片的點擊,當點擊到某張圖片的時候,將封裝好的蒙板和對勾,蓋在上面,或是再移除

 3:

## 獲得自定義的所有相簿
```objc
// 獲得所有的自定義相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 遍歷所有的自定義相簿
for (PHAssetCollection *assetCollection in assetCollections) {

}
```

## 獲得相機膠卷相簿
```objc
// 獲得相機膠卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
```

## 獲得某個相簿的縮略圖
```objc
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步獲得圖片, 只會返回1張圖片
options.synchronous = YES;

// 獲得某個相簿中的所有PHAsset對象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
    CGSize size = CGSizeZero;

    // 從asset中獲得圖片
    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        NSLog(@"%@", result);
    }];
}
```

## 獲得某個相簿的原圖
```objc
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步獲得圖片, 只會返回1張圖片
options.synchronous = YES;

// 獲得某個相簿中的所有PHAsset對象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
    CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight);

    // 從asset中獲得圖片
    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        NSLog(@"%@", result);
    }];
}
```

## 利用UIImagePickerController挑選圖片
```objc
// UIImagePickerController : 可以從系統自帶的App(照片\相機)中獲得圖片

// 判斷相冊是否可以打開
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;

UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
// 打開照片應用(顯示所有相簿)
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 打開照片應用(只顯示"時刻"這個相簿)
// ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 照相機
// ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
[self presentViewController:ipc animated:YES completion:nil];

#pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
    // 銷毀控制器
    [picker dismissViewControllerAnimated:YES completion:nil];

    // 設置圖片
    self.imageView.image = info[UIImagePickerControllerOriginalImage];
}
```

## NaN錯誤
- 錯誤起因:0被當做除數, 比如 10 / 0

## 最簡單的方法保存圖片到相機膠卷
```objc
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

/**
 *  通過UIImageWriteToSavedPhotosAlbum函數寫入圖片完畢后就會調用這個方法
 *
 *  @param image       寫入的圖片
 *  @param error       錯誤信息
 *  @param contextInfo UIImageWriteToSavedPhotosAlbum函數的最后一個參數
 */
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    if (error) {
        [SVProgressHUD showErrorWithStatus:@"圖片保存失敗!"];
    } else {
        [SVProgressHUD showSuccessWithStatus:@"圖片保存成功!"];
    }
}
```

## 保存圖片到自定義相冊
```objc
- (IBAction)save {
    /*
     PHAuthorizationStatusNotDetermined,     用戶還沒有做出選擇
     PHAuthorizationStatusDenied,            用戶拒絕當前應用訪問相冊(用戶當初點擊了"不允許")
     PHAuthorizationStatusAuthorized         用戶允許當前應用訪問相冊(用戶當初點擊了"好")
     PHAuthorizationStatusRestricted,        因為家長控制, 導致應用無法方法相冊(跟用戶的選擇沒有關系)
     */

    // 判斷授權狀態
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
    if (status == PHAuthorizationStatusRestricted) { // 因為家長控制, 導致應用無法方法相冊(跟用戶的選擇沒有關系)
        [SVProgressHUD showErrorWithStatus:@"因為系統原因, 無法訪問相冊"];
    } else if (status == PHAuthorizationStatusDenied) { // 用戶拒絕當前應用訪問相冊(用戶當初點擊了"不允許")
        XMGLog(@"提醒用戶去[設置-隱私-照片-xxx]打開訪問開關");
    } else if (status == PHAuthorizationStatusAuthorized) { // 用戶允許當前應用訪問相冊(用戶當初點擊了"好")
        [self saveImage];
    } else if (status == PHAuthorizationStatusNotDetermined) { // 用戶還沒有做出選擇
        // 彈框請求用戶授權
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if (status == PHAuthorizationStatusAuthorized) { // 用戶點擊了好
                [self saveImage];
            }
        }];
    }
}

- (void)saveImage
{
    // PHAsset : 一個資源, 比如一張圖片\一段視頻
    // PHAssetCollection : 一個相簿

    // PHAsset的標識, 利用這個標識可以找到對應的PHAsset對象(圖片對象)
    __block NSString *assetLocalIdentifier = nil;

    // 如果想對"相冊"進行修改(增刪改), 那么修改代碼必須放在[PHPhotoLibrary sharedPhotoLibrary]的performChanges方法的block中
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        // 1.保存圖片A到"相機膠卷"中
        // 創建圖片的請求
        assetLocalIdentifier = [PHAssetCreationRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier;
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        if (success == NO) {
            [self showError:@"保存圖片失敗!"];
            return;
        }

        // 2.獲得相簿
        PHAssetCollection *createdAssetCollection = [self createdAssetCollection];
        if (createdAssetCollection == nil) {
            [self showError:@"創建相簿失敗!"];
            return;
        }

        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
            // 3.添加"相機膠卷"中的圖片A到"相簿"D中

            // 獲得圖片
            PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetLocalIdentifier] options:nil].lastObject;

            // 添加圖片到相簿中的請求
            PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection];

            // 添加圖片到相簿
            [request addAssets:@[asset]];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (success == NO) {
                [self showError:@"保存圖片失敗!"];;
            } else {
                [self showSuccess:@"保存圖片成功!"];;
            }
        }];
    }];
}

/**
 *  獲得相簿
 */
- (PHAssetCollection *)createdAssetCollection
{
    // 從已存在相簿中查找這個應用對應的相簿
    PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    for (PHAssetCollection *assetCollection in assetCollections) {
        if ([assetCollection.localizedTitle isEqualToString:XMGAssetCollectionTitle]) {
            return assetCollection;
        }
    }

    // 沒有找到對應的相簿, 得創建新的相簿

    // 錯誤信息
    NSError *error = nil;

    // PHAssetCollection的標識, 利用這個標識可以找到對應的PHAssetCollection對象(相簿對象)
    __block NSString *assetCollectionLocalIdentifier = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        // 創建相簿的請求
        assetCollectionLocalIdentifier = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:XMGAssetCollectionTitle].placeholderForCreatedAssetCollection.localIdentifier;
    } error:&error];

    // 如果有錯誤信息
    if (error) return nil;

    // 獲得剛才創建的相簿
    return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionLocalIdentifier] options:nil].lastObject;
}

- (void)showSuccess:(NSString *)text
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [SVProgressHUD showSuccessWithStatus:text];
    });
}

- (void)showError:(NSString *)text
{
    dispatch_async(dispatch_get_main_queue(), ^{
        [SVProgressHUD showErrorWithStatus:text];
    });
}
```

## Xcode插件的安裝路徑
```objc
/Users/用戶名/Library/Application Support/Developer/Shared/Xcode/Plug-ins
```

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM