fetch videos with duration less than 10 seconds - ios

I am integrating custom image picker and i have to show videos from camera roll whose duration is less than 10 seconds. Below code fetches all videos from gallery but i want to apply predicate to filter based on duration as well.
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true) ]
options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.video.rawValue)
assets = PHAsset.fetchAssets(with: options)
print(assets ?? "no video found")
collectionView.reloadData()
Please let me know if anyone has any idea regarding the same.
Thanks.

Just add the condition to the predicate
options.predicate = NSPredicate(format: "mediaType = %d AND duration < 10", PHAssetMediaType.video.rawValue)

Related

Swift: get assets from Photo Library with excluding subtypes

I want to get list of assets from Photo Library but exclude subtypes or assets from smartfolders such as smartAlbumBursts, smartAlbumLivePhotos, smartAlbumScreenshots
my code is
let options = PHFetchOptions()
options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: true) ]
options.predicate = predicate
let assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
I was trying to make predicate like that:
let predicateType = NSPredicate(format: "mediaSubtypes != %#",
PHAssetMediaSubtype.photoScreenshot as! CVarArg)
but 1. it crashes 2. i can add PHAssetMediaSubtype only for screenshot and livePhoto but not for burst photo.
I know that there is method
if let collection = PHAssetCollection.fetchAssetCollections(with: .smartAlbum,
subtype: .smartAlbumBursts, options: nil).firstObject {
but i am not sure how to use that metdhod or subtype for my purposes
Was trying to use representsBurst but have a crash:
let predicateType = NSPredicate(format: "representsBurst == %#", NSNumber(value: false))
reason: 'Unsupported predicate in fetch options: representsBurst == 0'
Please refer to the table of supported predicate and sort descriptor keys of PHFetchOptions.
I'd make an assumption that if an asset doesn't represent a burst then it doesn't have a burst identifier. You can combine it as you want:
let options = PHFetchOptions()
options.sortDescriptors = [ NSSortDescriptor(key: "creationDate", ascending: true) ]
// fetch all images with no burstIdentifier
options.predicate = NSPredicate(format: "burstIdentifier == nil")
var assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
// fetch all images with photoScreenshot media subtype
options.predicate = NSPredicate(format: "((mediaSubtype & %d) != 0)", PHAssetMediaSubtype.photoScreenshot.rawValue)
assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
// fetch all images with photoLive media subtype
options.predicate = NSPredicate(format: "((mediaSubtype & %d) != 0)", PHAssetMediaSubtype.photoLive.rawValue)
assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
// fetch all non-photoScreenshot and non-photoLive images
options.predicate = NSPredicate(format: "NOT (((mediaSubtype & %d) != 0) || ((mediaSubtype & %d) != 0))", PHAssetMediaSubtype.photoScreenshot.rawValue, PHAssetMediaSubtype.photoLive.rawValue)
assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
// fetch all non-photoScreenshot and non-photoLive images with no burstIdentifier
options.predicate = NSPredicate(format: "NOT (((mediaSubtype & %d) != 0) || ((mediaSubtype & %d) != 0)) && burstIdentifier == nil", PHAssetMediaSubtype.photoScreenshot.rawValue, PHAssetMediaSubtype.photoLive.rawValue)
assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: options)
NSPredicate is tricky. The way to say "not" is like this:
NSPredicate(
format: "!((assetCollectionSubtype & %d) == %d)",
PHAssetCollectionSubtype.smartAlbumBursts.rawValue)

How to fetch all assets from iPhone apart from camera roll?

How to fetch assets from all albums including images and videos ?
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
This code will fetch only images from camera roll.
You can use this code to fetch all assets from iPhone.
PHPhotoLibrary.shared().register(self as PHPhotoLibraryChangeObserver)
if fetchResult == nil {
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
}
we can fetch all photos including sync albums and user albums.
let fetchOptions = PHFetchOptions()
fetchOptions.includeAssetSourceTypes = [.typeUserLibrary, .typeiTunesSynced, .typeCloudShared]
let fetchResult = PHAsset.fetchAssets(with: fetchOptions)
fetchResult will be having all photos and videos in all albums.

Retrieve last photo from Photo Library (iOS)

I'm trying to retrieve the last photo (last item) from the photos library. I'm using the following code to do that:
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.fetchLimit = 1
let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
The thing is that I have added an image to my photos library which has an old creation date from like 2012. So even though that image is at the end of the list in the photos app it's not being retrieved because the creationDate is old. I tried using fetchOptions.sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)] to no avail.
Is there a way to fetch the last image from the photos library (independently of creationDate)?

Fetch only PHAssetCollections containing at least one photo

In iOS PhotoKit, I can fetch all non-empty albums like this:
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "estimatedAssetCount > 0")
let albumFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: albumFetchOptions)
albumFetchResult.enumerateObjects({ (collection, _, _) in
// Do something with the album...
})
Then I can get only photos from the album like this:
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetResourceType.photo.rawValue)
let fetchResults = PHAsset.fetchAssets(in: collection, options: fetchOptions)
But the first part can give me albums with only videos, which means that after I apply the predicate to the second part, the album will be empty. Is there a way to filter out those albums in the first part, before I start using them?
It seems that collections cannot be filtered like this without also fetching the items in the collections. See the docs for available fetch options; none allow filtering by number of a specific type of media.
The way I would achieve this is by fetching all albums created by the user, and then fetching the assets from the albums with a predicate that returns only images.
So to put it in code:
var userCollections: PHFetchResult<PHAssetCollection>!
// Fetching all PHAssetCollections with at least some media in it
let options = PHFetchOptions()
options.predicate = NSPredicate(format: "estimatedAssetCount > 0")
// Performing the fetch
userCollections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: options)
Next, fetch the assets from a collection that are images by specifying a predicate:
// Getting the specific collection (I assumed to use a tableView)
let collection = userCollections[indexPath.row]
let optionsToFilterImage = PHFetchOptions()
optionsToFilterImage.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
// Fetching the asset with the predicate to filter just images
let justImages = PHAsset.fetchAssets(in: collection, options: optionsToFilterImage)
Lastly, count the number of images:
if justImages.count > 0 {
// Display it
} else {
// The album has no images
}

PHFetchOptions() Photos Only Using PHAsset & PHAssetCollection

I am using a chunk from Apple's sample code here:
override func awakeFromNib() {
// Create a PHFetchResult object for each section in the table view.
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let allPhotos = PHAsset.fetchAssetsWithOptions(allPhotosOptions)
let smartAlbums = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .AlbumRegular, options: nil)
let topLevelUserCollections = PHCollectionList.fetchTopLevelUserCollectionsWithOptions(nil)
// Store the PHFetchResult objects and localized titles for each section.
self.sectionFetchResults = [allPhotos, smartAlbums, topLevelUserCollections]
self.sectionLocalizedTitles = ["", NSLocalizedString("Smart Albums", comment: ""), NSLocalizedString("Albums", comment: "")]
PHPhotoLibrary.sharedPhotoLibrary().registerChangeObserver(self)
}
This lists all Albums successfully.
What I Need:
I want to only list albums with photos, exclude videos. Also, exclude video's from getting listed inside of albums, such as inside "All Photos".
What I tried:
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.Image.rawValue)
This causes to crash saying 'Unsupported predicate in fetch options: mediaType == 1'
I know this is a very late answer, but in case someone like me gets here, you should use this method to retrieve a media type. In this case PHAssetMediaType.image
func fetchAssets(with mediaType: PHAssetMediaType, options: PHFetchOptions?) -> PHFetchResult<PHAsset>
So in Swift 5 it writes as
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: .image, options: allPhotosOptions)
So far it works fine to me :
let allAlbums = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: nil)
let someAlbum = allAlbums.object(at: 0)
let onlyPhotoOption = PHFetchOptions()
onlyPhotoOption.predicate = NSPredicate(format: "mediaType == %i", PHAssetMediaType.image.rawValue)
let photos = PHAsset.fetchAssets(in: someAlbum, options: onlyPhotoOption)

Resources