Как получить только изображения в фотопленке с помощью Photos Framework
Следующий код загружает изображения, которые также находятся в iCloud, или изображения потоков. Как мы можем ограничить поиск только изображениями в рулоне камеры?
var assets = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: nil)
8 ответов
В результате некоторых экспериментов мы обнаружили скрытое свойство, не указанное в документации (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)
После добавления альбомов Camera Roll и Photo Stream Apple добавила следующее PHAssetCollectionSubtype
типы в iOS 8.1:
PHAssetCollectionSubtypeAlbumMyPhotoStream
(вместе сPHAssetCollectionTypeAlbum
) - получает альбом Photo Stream.PHAssetCollectionSubtypeSmartAlbumUserLibrary
(вместе сPHAssetCollectionTypeSmartAlbum
) - извлекает альбом Camera Roll.
Не проверял, если это обратно совместимо с iOS 8.0.x, хотя.
Если вы ищете, как и я, код Objective C, а также вы не получили ответа о новой библиотеке / фоторамке, так как получали устаревший код AssetsLibrary, то это поможет вам:Swift
Глобальные переменные:
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
Цель С
Глобальные переменные:
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
}
Это может помочь. Вы можете использовать свою собственную модель данных вместо 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
}
Если вы используете свой собственный PHCachingImageManager
вместо общего PHImageManager
экземпляр тогда, когда вы звоните requestImageForAsset:targetSize:contentMode:options:resultHandler:
Вы можете установить опцию в PHImageRequestOptions
указать, что изображение является локальным.
networkAccessAllowed Property
Логическое значение, которое указывает, может ли приложение Photos загружать запрошенное изображение из iCloud.
networkAccessAllowed
обсуждение
Если ДА, а запрошенное изображение не сохранено на локальном устройстве, Photos загружает изображение из iCloud. Чтобы получать уведомления о ходе загрузки, используйте свойство progressHandler, чтобы предоставить блок, который Photos периодически вызывает при загрузке изображения. Если НЕТ (по умолчанию), а изображение отсутствует на локальном устройстве, значение PHImageResultIsInCloudKey в информационном словаре обработчика результатов означает, что изображение недоступно, если вы не включите доступ к сети.
Я тоже бился головой об этом. Я не нашел способа фильтровать только активы на устройстве с помощью 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");
}
}];
}
Вот объективная версия, предоставленная Apple.
-(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**
Демонстрационная ссылка Apple
Объявите вашу собственность
@property (nonatomic, strong) NSArray *sectionFetchResults;
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
@property (nonatomic, strong) PHAssetCollection *assetCollection;
@property (nonatomic, strong) NSMutableArray *numberOfPhotoArray;
Если вы не хотите полагаться на недокументированный API, посмотрите на [asset canPerformEditOperation:PHAssetEditOperationContent]
, Это возвращает true, только если на устройстве доступен полный оригинал.
По общему признанию это также хрупко, но тестирование показывает, что это работает для всех типов assetSource (фотопоток, синхронизация iTunes и т. Д.).