24

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

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

8 回答 8

21

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

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

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

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

于 2015-01-21T09:22:59.177 回答
5

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

示例代码:

//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)
于 2014-09-08T20:29:11.810 回答
5

如果您像我一样搜索 Objective C 代码,并且您在使用已弃用的 AssetsLibrary 代码时没有得到新库/照片框架的答案,那么这将对您有所帮助: Swift

全局变量:

  func getAllPhotosFromCameraRoll() -> [UIImage] {
    // TODO: Add `NSPhotoLibraryUsageDescription` to info.plist
    PHPhotoLibrary.requestAuthorization { print($0) } // TODO: Move this line of code to somewhere before attempting to access photos

    var images = [UIImage]()

    let requestOptions: PHImageRequestOptions = PHImageRequestOptions()
    requestOptions.resizeMode = .exact
    requestOptions.deliveryMode = .highQualityFormat
    requestOptions.isSynchronous = true

    let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: .image, options: nil)
    let manager: PHImageManager = PHImageManager.default()

    for i in 0..<fetchResult.count {
      let asset = fetchResult.object(at: i)
      manager.requestImage(
        for: asset,
        targetSize: PHImageManagerMaximumSize,
        contentMode: .default,
        options: requestOptions,
        resultHandler: { (image: UIImage?, info: [AnyHashable: Any]?) -> Void in
          if let image = image {
            images.append(image)
          }
        })
    }

    return images
  }

目标 C

全局变量:

NSArray *imageArray;
NSMutableArray *mutableArray;

以下方法将帮助您:

-(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
}
于 2016-03-02T09:13:05.180 回答
4

这可以提供帮助。您可以使用自己的数据模型代替我使用的 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

        }
于 2017-10-10T15:04:24.767 回答
4

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

networkAccessAllowed 属性

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

网络访问允许

讨论

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

于 2016-04-30T12:08:47.610 回答
0

我也一直在为此头疼。我发现无法使用 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");
                                   }
                               }];

}
于 2017-07-28T14:10:04.190 回答
0

这是苹果提供的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;
}

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

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**

苹果演示链接

申报您的财产

@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;
于 2016-06-28T05:45:22.963 回答
-1

如果您不想依赖未记录的 API,请查看[asset canPerformEditOperation:PHAssetEditOperationContent]. 仅当设备上提供完整的原件时才返回 true。

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

于 2014-09-29T21:31:00.253 回答