【问题标题】:iOS save photo in an app specific albumiOS 将照片保存在特定应用的相册中
【发布时间】:2012-08-15 15:20:51
【问题描述】:

我正在创建一个 iOS 5 应用程序。我想将照片保存到设备中。

我想将照片保存到特定于我的应用的相册中,因此我需要创建相册,然后将照片保存到相册中。

我知道如何创建相册:

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library addAssetsGroupAlbumWithName:@"MY APP NAME" resultBlock:^(ALAssetsGroup *group) {
    //How to get the album URL?
} failureBlock:^(NSError *error) {
    //Handle the error
}];

我现在想将照片添加到新相册,我该怎么做?示例代码非常感谢!

【问题讨论】:

  • This article 似乎可以通过自定义 ALAssetsLibrary 类别实现您正在寻找的东西。看起来文章下面有一些有用的 cmets 也可能有助于提高性能。

标签: iphone objective-c ios camera alassetslibrary


【解决方案1】:

您可以使用以下代码更改专辑名称:

__weak ALAssetsLibrary *lib = self.library;

[self.library addAssetsGroupAlbumWithName:@"My Photo Album" resultBlock:^(ALAssetsGroup *group) {

    ///checks if group previously created
    if(group == nil){

        //enumerate albums
        [lib enumerateGroupsWithTypes:ALAssetsGroupAlbum
                           usingBlock:^(ALAssetsGroup *g, BOOL *stop)
         {
             //if the album is equal to our album
             if ([[g valueForProperty:ALAssetsGroupPropertyName] isEqualToString:@"My Photo Album"]) {

                 //save image
                 [lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
                                       completionBlock:^(NSURL *assetURL, NSError *error) {

                                           //then get the image asseturl
                                           [lib assetForURL:assetURL
                                                resultBlock:^(ALAsset *asset) {
                                                    //put it into our album
                                                    [g addAsset:asset];
                                                } failureBlock:^(NSError *error) {

                                                }];
                                       }];

             }
         }failureBlock:^(NSError *error){

         }];

    }else{
        // save image directly to library
        [lib writeImageDataToSavedPhotosAlbum:UIImagePNGRepresentation(image) metadata:nil
                              completionBlock:^(NSURL *assetURL, NSError *error) {

                                  [lib assetForURL:assetURL
                                       resultBlock:^(ALAsset *asset) {

                                           [group addAsset:asset];

                                       } failureBlock:^(NSError *error) {

                                       }];
                              }];
    }

} failureBlock:^(NSError *error) {

}];

【讨论】:

  • 太好了,它的工作。我在声明 ALAssetsLibrary *lib 时删除了 __weak,因为 completionBlock 没有调用。
【解决方案2】:

对于希望从 iOS 9 开始执行此操作的任何人,由于 ALAssetsLibrary 已被弃用,取而代之的是新的照片库,因此事情变得有些复杂。

这里有一些用于将 UIImages 添加到特定专辑名称的 Swift 代码(如果专辑不存在,则创建该专辑),您可能需要根据需要进行一些重构/优化:

func insertImage(image : UIImage, intoAlbumNamed albumName : String) {

    //Fetch a collection in the photos library that has the title "albumNmame"
    let collection = fetchAssetCollectionWithAlbumName(albumName)

    if collection == nil {
        //If we were unable to find a collection named "albumName" we'll create it before inserting the image
        PHPhotoLibrary.sharedPhotoLibrary().performChanges({
            PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle(albumName)
            }, completionHandler: {(success : Bool, error : NSError?) in
                if error != nil {
                    print("Error: " + error!.description)
                }

                if success {
                    //Fetch the newly created collection (which we *assume* exists here)
                    let newCollection = self.fetchAssetCollectionWithAlbumName(albumName)
                    self.insertImage(image, intoAssetCollection: newCollection!)
                }
            }
        )
    } else {
        //If we found the existing AssetCollection with the title "albumName", insert into it
        self.insertImage(image, intoAssetCollection: collection!)
    }
}

func fetchAssetCollectionWithAlbumName(albumName : String) -> PHAssetCollection? {

    //Provide the predicate to match the title of the album.
    let fetchOption = PHFetchOptions()
    fetchOption.predicate = NSPredicate(format: "title == '" + albumName + "'")

    //Fetch the album using the fetch option
    let fetchResult = PHAssetCollection.fetchAssetCollectionsWithType(
        PHAssetCollectionType.Album,
        subtype: PHAssetCollectionSubtype.AlbumRegular,
        options: fetchOption)

    //Assuming the album exists and no album shares it's name, it should be the only result fetched
    let collection = fetchResult.firstObject as? PHAssetCollection

    return collection
}

func insertImage(image : UIImage, intoAssetCollection collection : PHAssetCollection) {

    //Changes for the Photos Library must be maded within the performChanges block
    PHPhotoLibrary.sharedPhotoLibrary().performChanges({

            //This will request a PHAsset be created for the UIImage
            let creationRequest = PHAssetCreationRequest.creationRequestForAssetFromImage(image)

            //Create a change request to insert the new PHAsset in the collection
            let request = PHAssetCollectionChangeRequest(forAssetCollection: collection)

            //Add the PHAsset placeholder into the creation request.
            //The placeholder is used because the actual PHAsset hasn't been created yet
            if request != nil && creationRequest.placeholderForCreatedAsset != nil {
                request!.addAssets([creationRequest.placeholderForCreatedAsset!])
            }

        },

        completionHandler: { (success : Bool, error : NSError?) in
            if error != nil {
                print("Error: " + error!.description)
            }
        }
    )
}

【讨论】:

    【解决方案3】:

    对于那些在 Objective-C. 中寻找 Eddy 答案的人

    #import <Photos/Photos.h>

    - (void)insertImage:(UIImage *)image intoAlbumNamed:(NSString *)albumName {
        //Fetch a collection in the photos library that has the title "albumNmame"
        PHAssetCollection *collection = [self fetchAssetCollectionWithAlbumName: albumName];
    
        if (collection == nil) {
            //If we were unable to find a collection named "albumName" we'll create it before inserting the image
            [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle: albumName];
            } completionHandler:^(BOOL success, NSError * _Nullable error) {
                if (error != nil) {
                    NSLog(@"Error inserting image into album: %@", error.localizedDescription);
                }
    
                if (success) {
                    //Fetch the newly created collection (which we *assume* exists here)
                    PHAssetCollection *newCollection = [self fetchAssetCollectionWithAlbumName:albumName];
                    [self insertImage:image intoAssetCollection: newCollection];
                }
            }];
        } else {
            //If we found the existing AssetCollection with the title "albumName", insert into it
            [self insertImage:image intoAssetCollection: collection];
        }
    }
    
    - (PHAssetCollection *)fetchAssetCollectionWithAlbumName:(NSString *)albumName {
        PHFetchOptions *fetchOptions = [PHFetchOptions new];
        //Provide the predicate to match the title of the album.
        fetchOptions.predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"title == '%@'", albumName]];
    
        //Fetch the album using the fetch option
        PHFetchResult *fetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:fetchOptions];
    
        //Assuming the album exists and no album shares it's name, it should be the only result fetched
        return fetchResult.firstObject;
    }
    
    - (void)insertImage:(UIImage *)image intoAssetCollection:(PHAssetCollection *)collection {
        [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    
            //This will request a PHAsset be created for the UIImage
            PHAssetCreationRequest *creationRequest = [PHAssetCreationRequest creationRequestForAssetFromImage:image];
    
            //Create a change request to insert the new PHAsset in the collection
            PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection];
    
            //Add the PHAsset placeholder into the creation request.
            //The placeholder is used because the actual PHAsset hasn't been created yet
            if (request != nil && creationRequest.placeholderForCreatedAsset != nil) {
                [request addAssets: @[creationRequest.placeholderForCreatedAsset]];
            }
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (error != nil) {
                NSLog(@"Error inserting image into asset collection: %@", error.localizedDescription);
            }
        }];
    }
    

    【讨论】:

    • 是否可以只添加到该相册而不添加到相机胶卷?
    【解决方案4】:

    改编埃迪对 Swift 4 的回答:

        func saveImageToAlbum(_ image: UIImage, name: String) {
    
            if let collection = fetchAssetCollection(name) {
                self.saveImageToAssetCollection(image, collection: collection)
            } else {
                // Album does not exist, create it and attempt to save the image
                PHPhotoLibrary.shared().performChanges({
                    PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: name)
                }, completionHandler: { (success: Bool, error: Error?) in
                    guard success == true && error == nil else {
                        NSLog("Could not create the album")
                        if let err = error {
                            NSLog("Error: \(err)")
                        }
                        return
                    }
    
                    if let newCollection = self.fetchAssetCollection(name) {
                        self.saveImageToAssetCollection(image, collection: newCollection)
                    }
                })
            }
        }
    
        func fetchAssetCollection(_ name: String) -> PHAssetCollection? {
    
            let fetchOption = PHFetchOptions()
            fetchOption.predicate = NSPredicate(format: "title == '" + name + "'")
    
            let fetchResult = PHAssetCollection.fetchAssetCollections(
                with: PHAssetCollectionType.album,
                subtype: PHAssetCollectionSubtype.albumRegular,
                options: fetchOption)
    
            return fetchResult.firstObject
        }
    
        func saveImageToAssetCollection(_ image: UIImage, collection: PHAssetCollection) {
    
            PHPhotoLibrary.shared().performChanges({
    
                let creationRequest = PHAssetCreationRequest.creationRequestForAsset(from: image)
                if let request = PHAssetCollectionChangeRequest(for: collection),
                    let placeHolder = creationRequest.placeholderForCreatedAsset {
                    request.addAssets([placeHolder] as NSFastEnumeration)
                }
            }, completionHandler: { (success: Bool, error: Error?) in
                guard success == true && error == nil else {
                    NSLog("Could not save the image")
                    if let err = error {
                        NSLog("Error: " + err.localizedDescription)
                    }
                    return
                }
            })
        }
    

    【讨论】:

      【解决方案5】:

      Objective C 的改进版本,使用块。如果相册不存在,它会创建一个相册,然后保存三种类型的媒体项目 - 照片、GIF 和视频:

      // Types of media, that can be saved to an album
      typedef NS_ENUM(NSUInteger, AlbumMediaType) {
          AlbumMediaTypePhoto,
          AlbumMediaTypeGIF,
          AlbumMediaTypeVideo
      };
      
      /**
       Creates album if it doesn't exist and returns it in a block
       */
      - (void)createCollectionOnComplete:(void (^ _Nonnull)(PHAssetCollection * _Nonnull collection))onComplete
      {
          NSString *albumTitle = @"YOUR_ALBUM_TITLE";
      
          __block PHAssetCollection *collection;
          __block PHObjectPlaceholder *placeholder;
      
          // Searching for an existing album
          PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
          fetchOptions.predicate = [NSPredicate predicateWithFormat:@"title = %@", albumTitle];
          collection = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
                                                                subtype:PHAssetCollectionSubtypeAny
                                                                options:fetchOptions].firstObject;
          // If album is not found, we create it
          if (!collection)
          {
              [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
                  PHAssetCollectionChangeRequest *createAlbum = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:albumTitle];
                  placeholder = [createAlbum placeholderForCreatedAssetCollection];
              } completionHandler:^(BOOL success, NSError *error) {
                  if (success)
                  {
                      PHFetchResult *collectionFetchResult = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[placeholder.localIdentifier]
                                                                                                                  options:nil];
                      collection = collectionFetchResult.firstObject;
                      // After creating album, we return it
                      onComplete(collection);
                  }
              }];
          } else {
              // If album already exists, we instantly return it
              onComplete(collection);
          }
      }
      
      
      /**
       Saves an item of a given mediatype, that is located in mediaURL
       */
      - (void)saveToAlbumMediaItemFromURL:(NSURL *)mediaURL mediaType:(AlbumMediaType)mediaType
      {
          NSData *mediaData = [NSData dataWithContentsOfURL:mediaURL];
          if (!mediaData) {
              OWSFail(@"%@ Could not load data: %@", self.logTag, [self.attachmentStream mediaURL]);
              return;
          }
      
          [self createCollectionOnComplete:^(PHAssetCollection * _Nonnull collection) {
      
              [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
      
                  // We create a PHAsset using creationRequest
                  PHAssetCreationRequest *assetRequest;
                  switch (mediaType) {
                      case AlbumMediaTypePhoto: {
                          assetRequest = [PHAssetCreationRequest creationRequestForAssetFromImage:[UIImage imageWithData:mediaData]];
                          break;
                      }
                      case AlbumMediaTypeGIF: {
                          assetRequest = [PHAssetCreationRequest creationRequestForAsset];
                          PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
                          [assetRequest addResourceWithType:PHAssetResourceTypePhoto data:mediaData options:options];
                          break;
                      }
                      case AlbumMediaTypeVideo: {
                          if ( !UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(mediaURL.path) ) {
                              OWSFail(@"%@ Could not save incompatible video data.", self.logTag);
                              break;
                          }
      
                          NSString *videoPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"file.mov"];
                          [mediaData writeToFile:videoPath atomically:YES];
                          assetRequest = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:videoPath]];
                          break;
                      }
                      default:
                          break;
                  }
      
                  // Creating a request to change an album
                  PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:collection];
      
                  // PHAsset is not created yet, so we use a placeholder
                  PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset];
      
                  // We add a placeholder of a created item to the request of changing album
                  if (albumChangeRequest != nil && placeholder != nil) {
                      [albumChangeRequest addAssets: @[placeholder]];
                  }
      
              } completionHandler:^(BOOL success, NSError *error) {
      
                  if (success) {
                      NSLog(@"Media item saved!");
                  } else {
                      NSLog(@"Error saving media item - %@", error ? error.localizedDescription : @"");
                  }
      
              }];
      
          }];
      }
      

      我们可以使用这些方法以这种方式保存媒体项目:

      [self saveToAlbumMediaItemFromURL:[self.attachmentStream mediaURL] mediaType:AlbumMediaTypeGIF];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-05
        • 2012-06-12
        相关资源
        最近更新 更多