Collect Photos of iPhone Library taken between two

2019-08-11 05:07发布

问题:

I'm trying to create a simple controller in swift that allows me to collect photos from the library taken between two precise dates, e.g February the 15th 2015, an February the 18th 2015. During my searches I read about the Photo Framework of iOS, and I'd like to know if there's a simple way to query the photo library with such a framework based on the dates mentioned above. I'd like also to get images metadata like geo location for example. It'd be great if I could do that with the same framework Thanks for your answers

回答1:

To collect the photos between two dates, first you need to create NSDates representing the start and end of the date range. Here's a NSDate extension (from https://stackoverflow.com/a/24090354/2274694) that can create the dates from their string representations:

extension NSDate {
    convenience
    init(dateString:String) {
        let dateStringFormatter = NSDateFormatter()
        dateStringFormatter.dateFormat = "MM-dd-yyyy"
        dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
        let d = dateStringFormatter.dateFromString(dateString)!
        self.init(timeInterval:0, sinceDate:d)
    }
}

Then use the NSDates to create a predicate for the PHFetchResult's PHFetchOptions.

import Photos

class ViewController: UIViewController {

    var images:[UIImage] = [] // <-- Array to hold the fetched images

    override func viewDidLoad() {
        fetchPhotosInRange(NSDate(dateString:"04-06-2015"), endDate: NSDate(dateString:"04-16-2015"))
    }

    func fetchPhotosInRange(startDate:NSDate, endDate:NSDate) {

        let imgManager = PHImageManager.defaultManager()

        let requestOptions = PHImageRequestOptions()
        requestOptions.synchronous = true
        requestOptions.networkAccessAllowed = true

        // Fetch the images between the start and end date
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate, endDate)

        images = []

        if let fetchResult: PHFetchResult = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions) {
            // If the fetch result isn't empty,
            // proceed with the image request
            if fetchResult.count > 0 {
                // Perform the image request
                for var index = 0 ; index < fetchResult.count ; index++ {
                    let asset = fetchResult.objectAtIndex(index) as! PHAsset
                    imgManager.requestImageDataForAsset(asset, options: requestOptions, resultHandler: { (imageData: NSData?, dataUTI: String?, orientation: UIImageOrientation, info: [NSObject : AnyObject]?) -> Void in
                        if let imageData = imageData {
                            if let image = UIImage(data: imageData) {
                            // Add the returned image to your array
                                self.images += [image]
                            }
                        }
                        if self.images.count == fetchResult.count {
                            // Do something once all the images 
                            // have been fetched. (This if statement
                            // executes as long as all the images
                            // are found; but you should also handle
                            // the case where they're not all found.)
                        }
                    })
                }
            }
        }
    }
}

Updated for Swift 3:

import UIKit
import Photos

class ViewController: UIViewController {

    var images:[UIImage] = [] // <-- Array to hold the fetched images

    override func viewDidLoad() {
        let formatter = DateFormatter()
        formatter.dateFormat = "MM-dd-yyyy"
        fetchPhotosInRange(startDate: formatter.date(from: "04-06-2015")! as NSDate, endDate: formatter.date(from: "04-16-2015")! as NSDate)
    }

    func fetchPhotosInRange(startDate:NSDate, endDate:NSDate) {

        let imgManager = PHImageManager.default()

        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = true
        requestOptions.isNetworkAccessAllowed = true

        // Fetch the images between the start and end date
        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate, endDate)

        images = []

        let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions)
        // If the fetch result isn't empty,
        // proceed with the image request
        if fetchResult.count > 0 {
            // Perform the image request
            for index in 0  ..< fetchResult.count  {
                let asset = fetchResult.object(at: index)
                imgManager.requestImageData(for: asset, options: requestOptions, resultHandler: { (imageData: Data?, dataUTI: String?, orientation: UIImageOrientation, info: [AnyHashable : Any]?) -> Void in
                    if let imageData = imageData {
                        if let image = UIImage(data: imageData) {
                            // Add the returned image to your array
                            self.images += [image]
                        }
                    }
                    if self.images.count == fetchResult.count {
                        // Do something once all the images
                        // have been fetched. (This if statement
                        // executes as long as all the images
                        // are found; but you should also handle
                        // the case where they're not all found.)
                        print(self.images)
                    }
                })
            }
        }
    }
}


回答2:

First of all I want to say thanks to 'Lyndsey Scott' for such a wonderful code she did. It's really helpful. May be returning errors to few compiler as those are latest one and the code need to be updated a little. So Here I am giving the latest updated code to make Lyndsey's code error free for latest compiler for Swift 4.0 or above.

extension NSDate {
convenience
init(dateString:String) {
    let dateStringFormatter = DateFormatter()
    dateStringFormatter.dateFormat = "MM-dd-yyyy"
    dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale?
    let d = dateStringFormatter.date(from: dateString)!
    self.init(timeInterval: 0, since: d)
}

}

Then use the NSDates to create a predicate for the PHFetchResult's PHFetchOptions.

import UIKit
import Photos

class ViewController: UIViewController {

var images:[UIImage] = [] // <-- Array to hold the fetched images

override func viewDidLoad() {
    super.viewDidLoad()
    fetchPhotosInRange(startDate: NSDate(dateString:"07-15-2018"), endDate: NSDate(dateString:"07-31-2018"))

}

func fetchPhotosInRange(startDate:NSDate, endDate:NSDate)  {

    let imgManager = PHImageManager.default()

    let requestOptions = PHImageRequestOptions()
    requestOptions.isSynchronous = true
    requestOptions.isNetworkAccessAllowed = true

    // Fetch the images between the start and end date
    let fetchOptions = PHFetchOptions()
    fetchOptions.predicate = NSPredicate(format: "creationDate > %@ AND creationDate < %@", startDate, endDate)

    images = []

    if let fetchResult: PHFetchResult = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fetchOptions) {
        // If the fetch result isn't empty,
        // proceed with the image request
        if fetchResult.count > 0 {
            // Perform the image request
           for (index) in 0 ..< fetchResult.count {

           // for var index = 0 ; index < fetchResult.count ; index++ {
            let asset = fetchResult.object(at: index)
            // Request Image
            imgManager.requestImageData(for: asset, options: requestOptions, resultHandler: { (imageData, str, orientation, info) -> Void in

                    if let imageData = imageData {
                        if let image = UIImage(data: imageData) {
                            // Add the returned image to your array
                            self.images += [image]
                        }
                    }
                    if self.images.count == fetchResult.count {
                        // Do something once all the images
                        // have been fetched. (This if statement
                        // executes as long as all the images
                        // are found; but you should also handle
                        // the case where they're not all found.)
                    }
                })
            }
        }
    }
    print("images ==>\(images)")

}

Happy coding..