从Photos.app获取最后一张图片?

2020/12/03 09:22 · ios ·  · 0评论

我见过其他应用程序可以在其中从“照片”应用程序导入最后一张照片以进行快速使用,但据我所知,我只知道如何获得一张图像,而不是最后一张(最近一张)。谁能告诉我如何获取最后一张图片?

此代码段将从相机胶卷(iOS 7及更低版本)中获取最新图像

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

// Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

    // Within the group enumeration block, filter to enumerate just photos.
    [group setAssetsFilter:[ALAssetsFilter allPhotos]];

    // Chooses the photo at the last index
    [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

        // The end of the enumeration is signaled by asset == nil.
        if (alAsset) {
            ALAssetRepresentation *representation = [alAsset defaultRepresentation];
            UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]];

            // Stop the enumerations
            *stop = YES; *innerStop = YES;

            // Do something interesting with the AV asset.
            [self sendTweet:latestPhoto];
        }
    }];
} failureBlock: ^(NSError *error) {
    // Typically you should handle an error more gracefully than this.
    NSLog(@"No groups");
}];

iOS 8及更高版本:

PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
PHAsset *lastAsset = [fetchResult lastObject];
[[PHImageManager defaultManager] requestImageForAsset:lastAsset
                                          targetSize:self.photoLibraryButton.bounds.size
                                         contentMode:PHImageContentModeAspectFill
                                             options:PHImageRequestOptionsVersionCurrent
                                       resultHandler:^(UIImage *result, NSDictionary *info) {

                                           dispatch_async(dispatch_get_main_queue(), ^{

                                               [[self photoLibraryButton] setImage:result forState:UIControlStateNormal];

                                           });
                                       }];

iBrad的好回答对我来说几乎完美。例外是它以原始方向(例如,上下颠倒,-90°等)返回图像。

为了解决这个问题,我只是更改fullResolutionImagefullScreenImage

这里:

UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]];

现在,它可以治疗。

iBrad的示例包含一个显然起作用的iOS8代码段,但我发现自己对他描述的返回类型感到困惑。这是捕获最后一张图像的代码片段,包括版本和大小要求的选项。

值得注意的是可以请求特定版本(原始,当前)和大小的功能。就我而言,由于我希望将返回的图像应用于按钮,因此我要求将其大小和比例调整为适合要应用到的按钮:

PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions];
PHAsset *lastAsset = [fetchResult lastObject];
[[PHImageManager defaultManager] requestImageForAsset:lastAsset
                                          targetSize:self.photoLibraryButton.bounds.size
                                         contentMode:PHImageContentModeAspectFill
                                             options:PHImageRequestOptionsVersionCurrent
                                       resultHandler:^(UIImage *result, NSDictionary *info) {

                                           dispatch_async(dispatch_get_main_queue(), ^{

                                               [[self photoLibraryButton] setImage:result forState:UIControlStateNormal];

                                           });
                                       }];

感谢您的回答iBrad Apps。

只想指出一种特殊情况下的错误预防措施,即用户照片胶卷上没有图像时(我知道这是奇怪的情况):

    // Within the group enumeration block, filter to enumerate just photos.
    [group setAssetsFilter:[ALAssetsFilter allPhotos]];

    //Check that the group has more than one picture
    if ([group numberOfAssets] > 0) {
        // Chooses the photo at the last index
        [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:([group numberOfAssets] - 1)] options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

            // The end of the enumeration is signaled by asset == nil.
            if (alAsset) {
                ALAssetRepresentation *representation = [alAsset defaultRepresentation];
                UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullScreenImage]];

                [self.libraryButton setImage:latestPhoto forState:UIControlStateNormal];
            }
        }];
    }
    else {
      //Handle this special case
    }

好吧,这是一个如何使用Swift 3家伙从图库中加载最后一张图像的解决方案

func loadLastImageThumb(completion: @escaping (UIImage) -> ()) {
    let imgManager = PHImageManager.default()
    let fetchOptions = PHFetchOptions()
    fetchOptions.fetchLimit = 1
    fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]

    let fetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)

    if let last = fetchResult.lastObject {
        let scale = UIScreen.main.scale
        let size = CGSize(width: 100 * scale, height: 100 * scale)
        let options = PHImageRequestOptions()


        imgManager.requestImage(for: last, targetSize: size, contentMode: PHImageContentMode.aspectFill, options: options, resultHandler: { (image, _) in
            if let image = image {
                completion(image)
            }
        })
    }

}

如果需要更高的速度,也可以使用PHImageRequestOptions和设置这些速度:

options.deliveryMode = .fastFormat
options.resizeMode = .fast

这是您在viewController中获取它的方式(您应使用类替换GalleryManager.manager):

GalleryManager.manager.loadLastImageThumb { [weak self] (image) in
      DispatchQueue.main.async {
           self?.galleryButton.setImage(image, for: .normal)
      }
}

请参阅利亚姆的答案。fullScreenImage将返回适合您设备屏幕尺寸的缩放图像。为了获得实际的图像尺寸:

  ALAssetRepresentation *representation = [alAsset defaultRepresentation];
  ALAssetOrientation orientation = [representation orientation];
  UIImage *latestPhoto = [UIImage imageWithCGImage:[representation fullResolutionImage] scale:[representation scale] orientation:(UIImageOrientation)orientation];                    

在以下位置引用Apple的ALAssetRepresentation类参考fullResolutionImage

要从CGImage创建正确旋转的UIImage对象,请使用imageWithCGImage:scale:orientation:或initWithCGImage:scale:orientation:,并传递方向值和scale的值。

我发现我为输入错误而感到尴尬的时间超过了我必须弄清楚的时间。也许它将节省别人一些时间。

在以下行之后,此行缺少冒号indexSetWithIndex

[group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:[group numberOfAssets] - 1]options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

在iBrad的答案的基础上,这是一个快速且肮脏的Swift版本,适用于iOS 8.1:

let imgManager = PHImageManager.defaultManager()
var fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: true)]
if let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) {
    imgManager.requestImageForAsset(fetchResult.lastObject as PHAsset, targetSize: self.destinationImageView.frame.size, contentMode: PHImageContentMode.AspectFill, options: nil, resultHandler: { (image, _) in
        self.destinationImageView.image = image
    })
}

注意:这需要iOS 8.0+。确保链接“照片”框架,并在文件中添加“导入照片”。

这是Swift中的一个版本,版本请求数据并将其转换为UIImage,因为所提供的版本每次都会返回一个空的UIImage。

    let fetchOptions = PHFetchOptions()
    fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]

    let fetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)

    if let lastAsset: PHAsset = fetchResult.lastObject as? PHAsset {
        let manager = PHImageManager.defaultManager()
        let imageRequestOptions = PHImageRequestOptions()

        manager.requestImageDataForAsset(lastAsset, options: imageRequestOptions) {
            (let imageData: NSData?, let dataUTI: String?,
             let orientation: UIImageOrientation,
             let info: [NSObject : AnyObject]?) -> Void in

             if let imageDataUnwrapped = imageData, lastImageRetrieved = UIImage(data: imageDataUnwrapped) {
                // do stuff with image

             }
        }
    }

这是iBrad和Javier的答案的组合(效果很好),但是我得到的是缩略图资源,而不是全分辨率图像。其他一些人可能会发现这很方便。

- (void)setCameraRollImage {
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];
        if ([group numberOfAssets] > 0) {
            // Chooses the photo at the last index
            [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:([group numberOfAssets] - 1)] options:0 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {
                // The end of the enumeration is signaled by asset == nil.
                if (alAsset) {
                    UIImage *latestPhoto = [UIImage imageWithCGImage:[alAsset thumbnail]];
                    [self.cameraRollButton setImage:latestPhoto forState:UIControlStateNormal];
                }
            }];
        }
    } failureBlock: ^(NSError *error) {
    }];
}

Xamarin.iOS版本的接受答案(如何获取最后一张图片),包括来自其他答案的所有通知:

  private void ChooseLastTakenPictureImplementation()
    {
        var library = new ALAssetsLibrary();
        // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
        library.Enumerate(ALAssetsGroupType.SavedPhotos, (ALAssetsGroup assetsGroup, ref bool stop) =>
            {
                if (stop || assetsGroup == null)
                {
                    return;
                }
                //Xamarin does not support ref parameters in nested lamba expressions
                var lambdaStop = false;
                //Check that the group has more than one picture
                if (assetsGroup.Count > 0)
                {
                    // Within the group enumeration block, filter to enumerate just photos.
                    assetsGroup.SetAssetsFilter(ALAssetsFilter.AllPhotos);
                    // Chooses the photo at the last index
                    assetsGroup.Enumerate(NSEnumerationOptions.Reverse, (ALAsset result, int index, ref bool innerStop) =>
                        {
                            // The end of the enumeration is signaled by asset == nil.
                            if (result != null)
                            {
                                var representation = result.DefaultRepresentation;
                                var latestPhoto = new UIImage(representation.GetImage(), representation.Scale, (UIImageOrientation)representation.Orientation);
                                // Stop the enumerations
                                lambdaStop = innerStop = true;
                                // Do something interesting with the AV asset.
                                HandleImageAutoPick(latestPhoto);
                            }
                        });
                    stop = lambdaStop;
                    return;
                }
                else
                {
                    //Handle this special case where user has no pictures
                }
            }, error =>
            {
                // Typically you should handle an error more gracefully than this.
                Debug.WriteLine(error.Description);
            });
    }

这是一种非常酷的方法,但是问题之一是您必须能够在运行时实例化PHPhotoLibrary和其他PHPhoto类,因为否则在iOS 7.XX上会出现链接错误,只是想指出这一点,因为我正在运行现在讨论这些问题。

另外,我相信您必须在Photos框架中建立弱链接,才能使该应用程序在装有iOS 8.XX和iOS 7.XX的两种设备上运行(尽管我尚未对此进行测试。)

我遇到的唯一问题是如何在运行时实例化PHPhotoLibrary。有人为此提供代码片段吗?

实际上,对于我正在开发的应用程序,我确实必须最终编写运行时代码以实例化PHPhotoLibrary类并调用PHotos框架方法,以便该应用程序可以同时在iOS 7.xx和iOS 8.xx上运行。问题,所以我提供了下面的代码->

// PHPhotoLibrary_class will only be non-nil on iOS 8.x.x
Class PHPhotoLibrary_class = NSClassFromString(@"PHPhotoLibrary");

if (PHPhotoLibrary_class) {

   /**
    *
    iOS 8..x. . code that has to be called dynamically at runtime and will not link on iOS 7.x.x ...

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title];
    } completionHandler:^(BOOL success, NSError *error) {
        if (!success) {
            NSLog(@"Error creating album: %@", error);
        }
    }];
    */

    // dynamic runtime code for code chunk listed above            
    id sharedPhotoLibrary = [PHPhotoLibrary_class performSelector:NSSelectorFromString(@"sharedPhotoLibrary")];

    SEL performChanges = NSSelectorFromString(@"performChanges:completionHandler:");

    NSMethodSignature *methodSig = [sharedPhotoLibrary methodSignatureForSelector:performChanges];

    NSInvocation* inv = [NSInvocation invocationWithMethodSignature:methodSig];
    [inv setTarget:sharedPhotoLibrary];
    [inv setSelector:performChanges];

    void(^firstBlock)() = ^void() {
        Class PHAssetCollectionChangeRequest_class = NSClassFromString(@"PHAssetCollectionChangeRequest");
        SEL creationRequestForAssetCollectionWithTitle = NSSelectorFromString(@"creationRequestForAssetCollectionWithTitle:");
        [PHAssetCollectionChangeRequest_class performSelector:creationRequestForAssetCollectionWithTitle withObject:albumName];

    };

    void (^secondBlock)(BOOL success, NSError *error) = ^void(BOOL success, NSError *error) {
       if (success) {
           [assetsLib enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
               if (group) {
                   NSString *name = [group valueForProperty:ALAssetsGroupPropertyName];
                   if ([albumName isEqualToString:name]) {
                       groupFound = true;
                       handler(group, nil);
                   }
               }
           } failureBlock:^(NSError *error) {
               handler(nil, error);
           }];
       }

       if (error) {
           NSLog(@"Error creating album: %@", error);
           handler(nil, error);
       }
   };

   // Set the first and second blocks.
   [inv setArgument:&firstBlock atIndex:2];
   [inv setArgument:&secondBlock atIndex:3];

   [inv invoke];

}
else {   
   // code that always creates an album on iOS 7.x.x but fails
   // in certain situations such as if album has been deleted
   // previously on iOS 8...x. .              
   [assetsLib addAssetsGroupAlbumWithName:albumName
       resultBlock:^(ALAssetsGroup *group) {
       handler(group, nil);
   } failureBlock:^(NSError *error) {
       NSLog( @"Failed to create album: %@", albumName);
       handler(nil, error);
   }];
}

以下代码适用于iOS7和iOS8。它还检查滤镜中是否有图像。在执行代码之前,您应该检查相册许可:

// get the latest image from the album
-(void)getLatestPhoto
{
    NSLog(@"MMM TGCameraViewController - getLatestPhoto");
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    // Enumerate just the photos and videos group by using ALAssetsGroupSavedPhotos.
    [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {

        // Within the group enumeration block, filter to enumerate just photos.
        [group setAssetsFilter:[ALAssetsFilter allPhotos]];

        // For this example, we're only interested in the last item [group numberOfAssets]-1 = last.
        if ([group numberOfAssets] > 0) {

            [group enumerateAssetsAtIndexes:[NSIndexSet indexSetWithIndex:[group numberOfAssets]-1]
                                    options:0
                                 usingBlock:^(ALAsset *alAsset, NSUInteger index, BOOL *innerStop) {

                                     // The end of the enumeration is signaled by asset == nil.
                                     if (alAsset) {
                                         ALAssetRepresentation *representation = [alAsset defaultRepresentation];
                                         // Do something interesting with the AV asset.
                                         UIImage *img = [UIImage imageWithCGImage:[representation fullScreenImage]];

                                         // use the photo here ...


                                         // we only need the first (most recent) photo -- stop the enumeration
                                         *innerStop = YES;
                                     }
                                 }];
        }
    }
    failureBlock: ^(NSError *error) {
       // Typically you should handle an error more gracefully than this.
       NSLog(@"No groups");
    }];
}  

(此代码是此处的修改版本。)

本文地址:http://ios.askforanswer.com/congphotos-apphuoquzuihouyizhangtupian.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!