How to loop through a photo gallery in swift with photos framework
Asked Answered
M

2

9

I have an app that creates a unique photo gallery for each ticket on my app. I need to figure out how to loop through that gallery so I can upload the images to the server one at a time. I followed these tutorials on youtube. (Video) I am currently using Swift as my language. my ultimate goal would be to have something like the following pseudo code.

//I need the following for loop example
for photo in gallery
{
    uploadToServer(photo)
}

//this function works already

func uploadToServer(photo:UIImage)
{
    callRest
    postPhoto
}

here is my code so far cannot figure out how to loop through. them though.

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", self.albumName)?
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)

if let first_Obj:AnyObject = collection.firstObject{
    //found the album
    self.assetCollection = collection.firstObject as PHAssetCollection
    self.albumFound = true
}
else { albumFound = false }
var i = collection.count
self.photoAssets = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)


self.photoAssets.enumerateObjectsUsingBlock{(object: AnyObject!,
    count: Int,
    stop: UnsafeMutablePointer<ObjCBool>) in

    if object is PHAsset{
        let asset = object as PHAsset
        println("Inside  If object is PHAsset, This is number 1")

        let imageSize = CGSize(width: asset.pixelWidth,
            height: asset.pixelHeight)

        /* For faster performance, and maybe degraded image */
        let options = PHImageRequestOptions()
        options.deliveryMode = .FastFormat

        imageManager.requestImageForAsset(asset,
            targetSize: imageSize,
            contentMode: .AspectFill,
            options: options,
            resultHandler: {
                (image, info)->Void in

                self.photo = image

                var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
                var server = defaults.objectForKey("imageServer") as String!
                var error: NSError? = nil

                var imageData = UIImageJPEGRepresentation(self.photo, 90)
                var url = NSURL(string: server)
                var request = NSMutableURLRequest(URL: url!)
                request.HTTPMethod = "POST"
                //request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
                request.HTTPBody = imageData

                var response: NSURLResponse? = nil

                let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)

                let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
                println("API Response: \(results)")

                /*
                /* The image is now available to us */
                self.sendPhotos(image)
                println("enum for image, This is number 2")*/


        })
    }
}
Myocardium answered 5/3, 2015 at 18:46 Comment(6)
Go right ahead. What's the hard part?Calctufa
I am having trouble of what to loop through, I am new to swift and iOS devlopment. I tried looping through my PHAssetCollection, wont let me so I tried looping throught my PHFetchResults same thing. Im not sure how the photos framework works.Myocardium
Did you watch the WWDC video about the Photos framework? It's pretty straightforward.Calctufa
I did watch the video, and again just now. It does not explain how to loop through images as if they are an array. At least i do not undertand how i can "fetch" them. I will add to my post with my codeMyocardium
@Calctufa After some research I came up with the above code using enumerateObjectsUsingBlock it seems to be working fine, but it is getting nil for the image data. Did I miss something? Thank youMyocardium
Your implementation of requestImageForAsset is madness. Keep in mind that the resultHandler is called (1) asynchronously and (2) multiple times for each image. Again, watch the video. They talk all about this. - Please note that your question has now completely morphed; you're asking something completely different now.Calctufa
M
10

So after some research and guidance from Matt I have figured it out. Here is how to do this. Make sure you execute this on the main thread as well so you have to set the options.synchronous = true. If not for some reason it does not have any value for the photos.

func getSyncPhotos()
{
    self.albumName = String(self.ticket_id!)

    let fetchOptions = PHFetchOptions()
    fetchOptions.predicate = NSPredicate(format: "title = %@", self.albumName)?
    let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)

    if let first_Obj:AnyObject = collection.firstObject{
        //found the album
        self.assetCollection = collection.firstObject as PHAssetCollection
        self.albumFound = true
    }
    else { albumFound = false }
    var i = collection.count
    self.photoAssets = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
    let imageManager = PHCachingImageManager()

    self.photoAssets.enumerateObjectsUsingBlock{(object: AnyObject!,
        count: Int,
        stop: UnsafeMutablePointer<ObjCBool>) in

        if object is PHAsset{
            let asset = object as PHAsset
            println("Inside  If object is PHAsset, This is number 1")

            let imageSize = CGSize(width: asset.pixelWidth,
                height: asset.pixelHeight)

            /* For faster performance, and maybe degraded image */
            let options = PHImageRequestOptions()
            options.deliveryMode = .FastFormat
            options.synchronous = true
            imageManager.requestImageForAsset(asset,
                targetSize: imageSize,
                contentMode: .AspectFill,
                options: options,
                resultHandler: {
                     image, info in
                    self.photo = image!
                    /* The image is now available to us */
                    self.sendPhotos(self.photo)
                    println("enum for image, This is number 2")


            })
        }
    }
}

func sendPhotos(uploadImage:UIImage)
{

    var defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
    var server = defaults.objectForKey("imageServer") as String!
    var error: NSError? = nil

    var imageData = UIImageJPEGRepresentation(uploadImage, 90)
    var url = NSURL(string: server)
    var request = NSMutableURLRequest(URL: url!)
    request.HTTPMethod = "POST"
    //request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
    request.HTTPBody = imageData

    var response: NSURLResponse? = nil

    let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)

    let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
    println("API Response: \(results)")
}
Myocardium answered 6/3, 2015 at 17:58 Comment(2)
Thanks a million buddy... I wasted two days searching this over the internet..!!Calve
Using this code memory is not being released until all images get fetched. If I am closing the view controller before this task is done then it leads to a memory leak.Frow
P
6
func fetchVideoFromLibrary() {
       let fetchOptions: PHFetchOptions = PHFetchOptions()
       fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
       let fetchResult = PHAsset.fetchAssetsWithMediaType(.Video, options: fetchOptions)
       fetchResult.enumerateObjectsUsingBlock { (object, index, stop) -> Void in
           let options = PHImageRequestOptions()
           options.synchronous = true
           options.deliveryMode = .HighQualityFormat
           PHImageManager.defaultManager().requestAVAssetForVideo(object as! PHAsset, options: .None) { (avAsset, avAudioMix, dict) -> Void in
               print(avAsset)
           }
       }
   }
Payola answered 2/5, 2016 at 11:33 Comment(1)
How to fetch videos from 10 to 20 , for example i want to show video using pagination , so wanna fetch 0 to 10, 10 to 20 .... etcPayola

© 2022 - 2024 — McMap. All rights reserved.