【问题标题】:How to save picture to iPhone photo library?如何将图片保存到 iPhone 照片库?
【发布时间】:2010-09-15 18:54:34
【问题描述】:

我需要做什么才能将我的程序生成的图像(可能来自相机,也可能不是)保存到 iPhone 上的系统照片库中?

【问题讨论】:

  • 您可以查看this code。美好的一天!

标签: ios iphone cocoa-touch camera uiimage


【解决方案1】:

你可以使用这个功能:

UIImageWriteToSavedPhotosAlbum(UIImage *image, 
                               id completionTarget, 
                               SEL completionSelector, 
                               void *contextInfo);

你只需要completionTargetcompletionSelectorcontextInfo,如果你想在UIImage完成保存时得到通知,否则你可以传入nil

请参阅official documentation for UIImageWriteToSavedPhotosAlbum()

【讨论】:

  • 为准确答案加1
  • 您好,感谢您的出色解决方案。在这里,我怀疑如何在照片库中保存图像时避免重复。提前致谢。
  • 如果您想以更好的质量保存,请参阅:stackoverflow.com/questions/1379274/…
  • 您现在需要从 iOS 11 添加“隐私 - 照片库添加使用说明”,以将照片保存到用户相册。
  • 如何给保存的图片命名?
【解决方案2】:

在 iOS 9.0 中已弃用。

使用 iOS 4.0+ AssetsLibrary 框架比 UIImageWriteToSavedPhotosAlbum 快得多

    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    [library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
    if (error) {
    // TODO: error handling
    } else {
    // TODO: success handling
    }
}];
[library release];

【讨论】:

  • 有没有办法将任意元数据与照片一起保存?
  • 我尝试使用ALAssetsLibrary保存,保存为UIImageWriteToSavedPhotosAlbum需要同样的时间。
  • 这会冻结相机:(我猜它不支持背景?
  • 这个更干净 b/c 你可以使用块来处理完成。
  • 我正在使用此代码,并且我包含此框架#import 而不是 AVFoundation。不应该编辑答案吗? @丹尼斯
【解决方案3】:

最简单的方法是:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

Swift可以参考Saving to the iOS photo library using swift

【讨论】:

  • 我真的很喜欢你的 SO 用户个人资料图标。很酷的 Xcode 图片。
  • 非常简单,非常简单!
【解决方案4】:

要记住的一点:如果您使用回调,请确保您的选择器符合以下形式:

- (void) image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo;

否则,您将因以下错误而崩溃:

[NSInvocation setArgument:atIndex:]: index (2) out of bounds [-1, 1]

【讨论】:

    【解决方案5】:

    像这样将图像从数组传递给它

    -(void) saveMePlease {
    
    //Loop through the array here
    for (int i=0:i<[arrayOfPhotos count]:i++){
             NSString *file = [arrayOfPhotos objectAtIndex:i];
             NSString *path = [get the path of the image like you would in DOCS FOLDER or whatever];
             NSString *imagePath = [path stringByAppendingString:file];
             UIImage *image = [[[UIImage alloc] initWithContentsOfFile:imagePath]autorelease];
    
             //Now it will do this for each photo in the array
             UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
            }
    }
    

    抱歉打错字了,但你明白了

    【讨论】:

    • 用这个会漏掉一些照片,我试过了。正确的方法是使用完成选择器的回调。
    • 我们可以用自定义名称保存图片吗?
    • 永远不要为此使用 for 循环。它会导致竞争条件和崩溃。
    【解决方案6】:

    保存一组照片时,不要使用for循环,请执行以下操作

    -(void)saveToAlbum{
       [self performSelectorInBackground:@selector(startSavingToAlbum) withObject:nil];
    }
    -(void)startSavingToAlbum{
       currentSavingIndex = 0;
       UIImage* img = arrayOfPhoto[currentSavingIndex];//get your image
       UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
    }
    - (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo{ //can also handle error message as well
       currentSavingIndex ++;
       if (currentSavingIndex >= arrayOfPhoto.count) {
           return; //notify the user it's done.
       }
       else
       {
           UIImage* img = arrayOfPhoto[currentSavingIndex];
           UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
       }
    }
    

    【讨论】:

      【解决方案7】:

      Swift 中:

          // Save it to the camera roll / saved photo album
          // UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, nil, nil, nil) or 
          UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, self, "image:didFinishSavingWithError:contextInfo:", nil)
      
          func image(image: UIImage!, didFinishSavingWithError error: NSError!, contextInfo: AnyObject!) {
                  if (error != nil) {
                      // Something wrong happened.
                  } else {
                      // Everything is alright.
                  }
          }
      

      【讨论】:

      • 是的...很好..但是保存图片后我想从图库中加载图片...怎么做
      【解决方案8】:

      下面的函数可以工作。您可以从这里复制并粘贴到那里...

      -(void)savePhotoToAlbum:(UIImage*)imageToSave {
      
          CGImageRef imageRef = imageToSave.CGImage;
          NSDictionary *metadata = [NSDictionary new]; // you can add
          ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
      
          [library writeImageToSavedPhotosAlbum:imageRef metadata:metadata completionBlock:^(NSURL *assetURL,NSError *error){
              if(error) {
                  NSLog(@"Image save eror");
              }
          }];
      }
      

      【讨论】:

        【解决方案9】:

        斯威夫特 4

        func writeImage(image: UIImage) {
            UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.finishWriteImage), nil)
        }
        
        @objc private func finishWriteImage(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
            if (error != nil) {
                // Something wrong happened.
                print("error occurred: \(String(describing: error))")
            } else {
                // Everything is alright.
                print("saved success!")
            }
        }
        

        【讨论】:

          【解决方案10】:

          我的最后一个答案会这样做..

          对于您要保存的每个图像,将其添加到 NSMutableArray

              //in the .h file put:
          
          NSMutableArray *myPhotoArray;
          
          
          ///then in the .m
          
          - (void) viewDidLoad {
          
           myPhotoArray = [[NSMutableArray alloc]init];
          
          
          
          }
          
          //However Your getting images
          
          - (void) someOtherMethod { 
          
           UIImage *someImage = [your prefered method of using this];
          [myPhotoArray addObject:someImage];
          
          }
          
          -(void) saveMePlease {
          
          //Loop through the array here
          for (int i=0:i<[myPhotoArray count]:i++){
                   NSString *file = [myPhotoArray objectAtIndex:i];
                   NSString *path = [get the path of the image like you would in DOCS FOLDER or whatever];
                   NSString *imagePath = [path stringByAppendingString:file];
                   UIImage *image = [[[UIImage alloc] initWithContentsOfFile:imagePath]autorelease];
          
                   //Now it will do this for each photo in the array
                   UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
                  }
          }
          

          【讨论】:

          • 我试过你的解决方案,它总是错过一些照片。看看我的回答。 link
          【解决方案11】:
          homeDirectoryPath = NSHomeDirectory();
          unexpandedPath = [homeDirectoryPath stringByAppendingString:@"/Pictures/"];
          
          folderPath = [NSString pathWithComponents:[NSArray arrayWithObjects:[NSString stringWithString:[unexpandedPath stringByExpandingTildeInPath]], nil]];
          
          unexpandedImagePath = [folderPath stringByAppendingString:@"/image.png"];
          
          imagePath = [NSString pathWithComponents:[NSArray arrayWithObjects:[NSString stringWithString:[unexpandedImagePath stringByExpandingTildeInPath]], nil]];
          
          if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:NULL]) {
              [[NSFileManager defaultManager] createDirectoryAtPath:folderPath attributes:nil];
          }
          

          【讨论】:

          • 这个答案是不对的,因为它不会将图像保存到系统照片库,而是保存到沙箱。
          【解决方案12】:

          根据上面的一些答案,我为此创建了一个 UIImageView 类别。

          头文件:

          @interface UIImageView (SaveImage) <UIActionSheetDelegate>
          - (void)addHoldToSave;
          @end
          

          实施

          @implementation UIImageView (SaveImage)
          - (void)addHoldToSave{
              UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
              longPress.minimumPressDuration = 1.0f;
              [self addGestureRecognizer:longPress];
          }
          
          -  (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
              if (sender.state == UIGestureRecognizerStateEnded) {
          
                  UIActionSheet* _attachmentMenuSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                                                    delegate:self
                                                                           cancelButtonTitle:@"Cancel"
                                                                      destructiveButtonTitle:nil
                                                                           otherButtonTitles:@"Save Image", nil];
                  [_attachmentMenuSheet showInView:[[UIView alloc] initWithFrame:self.frame]];
              }
              else if (sender.state == UIGestureRecognizerStateBegan){
                  //Do nothing
              }
          }
          -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
              if  (buttonIndex == 0) {
                  UIImageWriteToSavedPhotosAlbum(self.image, nil,nil, nil);
              }
          }
          
          
          @end
          

          现在只需在你的 imageview 上调用这个函数:

          [self.imageView addHoldToSave];
          

          您可以选择更改 minimumPressDuration 参数。

          【讨论】:

            【解决方案13】:

            Swift 2.2

            UIImageWriteToSavedPhotosAlbum(image: UIImage, _ completionTarget: AnyObject?, _ completionSelector: Selector, _ contextInfo: UnsafeMutablePointer<Void>)
            

            如果您不想在图像保存完成时收到通知,那么您可以在 completionTargetcompletionSelectorcontextInfo 中传递 nil参数。

            例子:

            UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)
            
            func imageSaved(image: UIImage!, didFinishSavingWithError error: NSError?, contextInfo: AnyObject?) {
                    if (error != nil) {
                        // Something wrong happened.
                    } else {
                        // Everything is alright.
                    }
                }
            

            这里要注意的重要一点是,你观察图像保存的方法应该有这 3 个参数,否则你会遇到 NSInvocation 错误。

            希望对您有所帮助。

            【讨论】:

              【解决方案14】:

              你可以用这个

              dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                 UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
              });
              

              【讨论】:

                【解决方案15】:

                对于 Swift 5.0

                我使用此代码将图像复制到我的应用程序创建的相册中; 当我想复制图像文件时,我调用“startSavingPhotoAlbume()”函数。 首先,我从 App 文件夹中获取 UIImage,然后将其保存到相册。 因为它无关紧要,所以我没有展示如何从 App 文件夹中读取图像。

                var saveToPhotoAlbumCounter = 0
                
                
                
                func startSavingPhotoAlbume(){
                    saveToPhotoAlbumCounter = 0
                    saveToPhotoAlbume()
                }
                
                func saveToPhotoAlbume(){  
                    let image = loadImageFile(fileName: imagefileList[saveToPhotoAlbumCounter], folderName: folderName)
                    UIImageWriteToSavedPhotosAlbum(image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
                }
                
                @objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
                    if (error != nil) {
                        print("ptoto albume savin error for \(imageFileList[saveToPhotoAlbumCounter])")
                    } else {
                        
                        if saveToPhotoAlbumCounter < imageFileList.count - 1 {
                            saveToPhotoAlbumCounter += 1
                            saveToPhotoAlbume()
                        } else {
                            print("saveToPhotoAlbume is finished with \(saveToPhotoAlbumCounter) files")
                        }
                    }
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-03-13
                  • 2012-06-12
                  • 1970-01-01
                  • 2015-10-20
                  相关资源
                  最近更新 更多