ios 如何使用照片框架仅获取相机胶卷中的图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25730830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:17:06  来源:igfitidea点击:

How to get only images in the camera roll using Photos Framework

iosswiftphotosframework

提问by William Falcon

The following code loads images that are also located on iCloud or the streams images. How can we limit the search to only images in the camera roll?

以下代码加载同样位于 iCloud 或流图像上的图像。我们如何将搜索限制为仅相机胶卷中的图像?

var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)

采纳答案by William Falcon

Through some experimentation we discovered a hidden property not listed in the documentation (assetSource). Basically you have to do a regular fetch request, then use a predicate to filter the ones from the camera roll. This value should be 3.

通过一些实验,我们发现了文档中未列出的隐藏属性 ( assetSource)。基本上,您必须执行常规获取请求,然后使用谓词从相机胶卷中过滤请求。该值应为 3。

Sample code:

示例代码:

//fetch all assets, then sub fetch only the range we need
var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)

assets.enumerateObjectsUsingBlock { (obj, idx, bool) -> Void in
    results.addObject(obj)
}

var cameraRollAssets = results.filteredArrayUsingPredicate(NSPredicate(format: "assetSource == %@", argumentArray: [3]))
results = NSMutableArray(array: cameraRollAssets)

回答by StatusReport

After adding the Camera Roll and Photo Stream albums, Apple added the following PHAssetCollectionSubtypetypes in iOS 8.1:

添加相机胶卷和照片流相册后,ApplePHAssetCollectionSubtype在 iOS 8.1 中添加了以下类型:

  1. PHAssetCollectionSubtypeAlbumMyPhotoStream(together with PHAssetCollectionTypeAlbum) - fetches the Photo Stream album.

  2. PHAssetCollectionSubtypeSmartAlbumUserLibrary(together with PHAssetCollectionTypeSmartAlbum) - fetches the Camera Roll album.

  1. PHAssetCollectionSubtypeAlbumMyPhotoStream(连同PHAssetCollectionTypeAlbum) - 获取 Photo Stream 相册。

  2. PHAssetCollectionSubtypeSmartAlbumUserLibrary(连同PHAssetCollectionTypeSmartAlbum) - 获取相机胶卷相册。

Haven't tested if this is backward-compatible with iOS 8.0.x though.

尚未测试这是否与 iOS 8.0.x 向后兼容。

回答by karan

If you are searching like me for Objective C code, and also you didn't get Answer of new library/ Photo Framework as you were getting deprecated AssetsLibrary's code , Then this will help you: Swift

如果你像我一样搜索 Objective C 代码,并且你没有得到新库/照片框架的答案,因为你得到了不推荐使用的 AssetsLibrary 代码,那么这将帮助你: Swift

Global Variables:

全局变量:

var imageArray: [AnyObject]
var mutableArray: [AnyObject]

convenience func getAllPhotosFromCamera() {
    imageArray = [AnyObject]()
    mutableArray = [AnyObject]()
    var requestOptions: PHImageRequestOptions = PHImageRequestOptions()
    requestOptions.resizeMode = .Exact
    requestOptions.deliveryMode = .HighQualityFormat
    requestOptions.synchronous = true
    var result: PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: nil)
    NSLog("%d", Int(result.count))
    var manager: PHImageManager = PHImageManager.defaultManager()
    var images: [AnyObject] = [AnyObject](minimumCapacity: result.count)
        // assets contains PHAsset objects.
    var ima: UIImage
    for asset: PHAsset in result {
        // Do something with the asset
        manager.requestImageForAsset(asset, targetSize: PHImageManagerMaximumSize, contentMode: .Default, options: requestOptions, resultHandler: {(image: UIImage, info: [NSObject : AnyObject]) -> void in

Objective C

目标 C

Global Variables:

全局变量:

NSArray *imageArray;
NSMutableArray *mutableArray;

below method will help you:

以下方法将帮助您:

-(void)getAllPhotosFromCamera
{
    imageArray=[[NSArray alloc] init];
    mutableArray =[[NSMutableArray alloc]init];

    PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
    requestOptions.resizeMode   = PHImageRequestOptionsResizeModeExact;
    requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
    requestOptions.synchronous = true;
    PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

    NSLog(@"%d",(int)result.count);

    PHImageManager *manager = [PHImageManager defaultManager];
    NSMutableArray *images = [NSMutableArray arrayWithCapacity:[result count]];

    // assets contains PHAsset objects.

    __block UIImage *ima;
    for (PHAsset *asset in result) {
        // Do something with the asset

        [manager requestImageForAsset:asset
                           targetSize:PHImageManagerMaximumSize
                          contentMode:PHImageContentModeDefault
                              options:requestOptions
                        resultHandler:^void(UIImage *image, NSDictionary *info) {
                            ima = image;

                            [images addObject:ima];
                        }];


    }

    imageArray = [images copy];  // You can direct use NSMutuable Array images
}

回答by jamesthakid

This can help. You can use your own data model instead of AlbumModel I used.

这可以提供帮助。您可以使用您自己的数据模型而不是我使用的 AlbumModel。

func getCameraRoll() -> AlbumModel {
          var cameraRollAlbum : AlbumModel!

          let cameraRoll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)

          cameraRoll.enumerateObjects({ (object: AnyObject!, count: Int, stop: UnsafeMutablePointer) in
            if object is PHAssetCollection {
              let obj:PHAssetCollection = object as! PHAssetCollection

              let fetchOptions = PHFetchOptions()
              fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
              fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
              let assets = PHAsset.fetchAssets(in: obj, options: fetchOptions)

              if assets.count > 0 {
                let newAlbum = AlbumModel(name: obj.localizedTitle!, count: assets.count, collection:obj, assets: assets)

                cameraRollAlbum = newAlbum
              }
            }
          })
         return cameraRollAlbum

        }

回答by Grimxn

If you use your own PHCachingImageManagerinstead of the shared PHImageManagerinstance then when you call requestImageForAsset:targetSize:contentMode:options:resultHandler:you can set an option in PHImageRequestOptionsto specify that the image is local.

如果您使用自己PHCachingImageManagerPHImageManager实例而不是共享实例,那么当您调用时,requestImageForAsset:targetSize:contentMode:options:resultHandler:您可以设置一个选项PHImageRequestOptions来指定图像是本地的。

networkAccessAllowedProperty

A Boolean value that specifies whether Photos can download the requested image from iCloud.

networkAccessAllowed

Discussion

If YES, and the requested image is not stored on the local device, Photos downloads the image from iCloud. To be notified of the download's progress, use the progressHandler property to provide a block that Photos calls periodically while downloading the image. If NO (the default), and the image is not on the local device, the PHImageResultIsInCloudKey value in the result handler's info dictionary indicates that the image is not available unless you enable network access.

networkAccessAllowed属性

一个布尔值,指定照片是否可以从 iCloud 下载请求的图像。

网络访问允许

讨论

如果是,并且请求的图像未存储在本地设备上,则照片将从 iCloud 下载图像。要获得下载进度的通知,请使用 progressHandler 属性提供一个块,供照片在下载图像时定期调用。如果 NO(默认值),并且图像不在本地设备上,则结果处理程序的信息字典中的 PHImageResultIsInCloudKey 值指示图像不可用,除非您启用网络访问。

回答by karthikeyan

Here is Objective- c version provided by apple.

这是苹果提供的Objective-c 版本。

-(NSMutableArray *)getNumberOfPhotoFromCameraRoll:(NSArray *)array{
    PHFetchResult *fetchResult = array[1];
    int index = 0;
    unsigned long pictures = 0;
    for(int i = 0; i < fetchResult.count; i++){
        unsigned long temp = 0;
        temp = [PHAsset fetchAssetsInAssetCollection:fetchResult[i] options:nil].count;
        if(temp > pictures ){
            pictures = temp;
            index = i;
        }
    }
    PHCollection *collection = fetchResult[index];

       if (![collection isKindOfClass:[PHAssetCollection class]]) {
        // return;
    }
    // Configure the AAPLAssetGridViewController with the asset collection.
    PHAssetCollection *assetCollection = (PHAssetCollection *)collection;
    PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
    self. assetsFetchResults = assetsFetchResult;
    self. assetCollection = assetCollection;
    self.numberOfPhotoArray = [NSMutableArray array];
    for (int i = 0; i<[assetsFetchResult count]; i++) {
        PHAsset *asset = assetsFetchResult[i];
        [self.numberOfPhotoArray addObject:asset];
    }
    NSLog(@"%lu",(unsigned long)[self.numberOfPhotoArray count]);
    return self.numberOfPhotoArray;
}

Where you can grab following details

您可以在哪里获取以下详细信息

PHFetchResult *fetchResult = self.sectionFetchResults[1];
        PHCollection *collection = fetchResult[6];
**value 1,6 used to get camera images**
**value 1,0 used to get screen shots**
**value 1,1 used to get hidden**
**value 1,2 used to get selfies** 
**value 1,3 used to get recently added**
**value 1,4 used to get videos**
**value 1,5 used to get recently deleted**
 **value 1,7 used to get favorites**

Apple demo link

苹果演示链接

Declare your property

申报您的财产

@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;

回答by Tom Kincaid

I've been banging my head over this too. I've found no way to filter for only assets on the device with fetchAssetsWithMediaType or fetchAssetsInAssetCollection. I'm able to use requestContentEditingInputWithOptions or requestImageDataForAsset to determine if the asset is on the device or not, but this is asynchronous and seems like it's using way too much resources to do for every asset in the list. There must be a better way.

我也一直在为这个头疼。我发现无法仅使用 fetchAssetsWithMediaType 或 fetchAssetsInAssetCollection 过滤设备上的资产。我可以使用 requestContentEditingInputWithOptions 或 requestImageDataForAsset 来确定资产是否在设备上,但这是异步的,似乎它使用太多资源来处理列表中的每个资产。一定会有更好的办法。

PHFetchResult *fetchResult = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:nil];

for (int i=0; i<[fetchResult count]; i++) {

    PHAsset *asset = fetchResult[i];

    [asset requestContentEditingInputWithOptions:nil
                               completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
                                   if ([[info objectForKey:PHContentEditingInputResultIsInCloudKey] intValue] == 1) {
                                       NSLog(@"asset is in cloud");
                                   } else {
                                       NSLog(@"asset is on device");
                                   }
                               }];

}

回答by delrox

If you don't want to rely on an undocumented API, look at [asset canPerformEditOperation:PHAssetEditOperationContent]. This only returns true if the full original is available on device.

如果您不想依赖未公开的 API,请查看[asset canPerformEditOperation:PHAssetEditOperationContent]. 如果设备上有完整的原件,这只会返回 true。

Admittedly this is also fragile, but testing shows it works for all of the assetSource types (photostream, iTunes sync, etc).

诚然,这也很脆弱,但测试表明它适用于所有资产来源类型(照片流、iTunes 同步等)。