user4513956 user4513956 - 5 months ago 86
Swift Question

How to load the Photo Library into UICollectionView? Swift

What I'm trying to accomplish: For this project, I will mention only two source files: (1) RPPhotoLibrary.swift - A UICollectionViewController and (2) PhotoThumbnail.swift: - A UICollectionViewCell. I want to load the images (and videos) from the user's photo library (preferably all of them) and present them into a UICollectionViewCell for each cell in the UICollectionViewController. For some reason, I am able to load photos but am not able to load all the photos. This is my code for the first source file: RPPhotoLibrary.swift:

import UIKit
import Photos

private let reuseIdentifier = "PhotoCell"

class RPPhotoLibrary: UICollectionViewController, UIImagePickerControllerDelegate {


// By default make locating album false
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult!
var assetThumbnailSize: CGSize!

@IBAction func cancelButton(sender: AnyObject) {
self.dismissViewControllerAnimated(false, completion: nil)
}

// =================== THIS BUTTON TAKES A PHOTO =====================================================
@IBAction func captureMoment(sender: AnyObject) {
let imagePicker = UIImagePickerController()

if (UIImagePickerController.isSourceTypeAvailable(.Camera)) {

if UIImagePickerController.availableCaptureModesForCameraDevice(.Rear) != nil {

imagePicker.allowsEditing = true
imagePicker.sourceType = .Camera
imagePicker.cameraCaptureMode = .Photo
presentViewController(imagePicker, animated: false, completion: {} )

} else {
// postAlert("Rear camera does not exist", message: "RedPlanet cannot access the camera")
var alert = UIAlertView(title: "Your phone doesn't have a rear camera!",
message: "RedPlanet cannot access the camera.",
delegate: self,
cancelButtonTitle: "ok")
alert.show()
}

} else {
// postAlert("Camera not accessible", message: "RedPlanet cannot access the camera")
var alert = UIAlertView(title: "Cannot access camera.",
message: "RedPlanet cannot access the camera.",
delegate: self,
cancelButtonTitle: "ok")
alert.show()
}
}

@IBOutlet weak var thumbNail: UIImageView!

override func viewDidLoad() {
super.viewDidLoad()

let fetchOptions = PHFetchOptions()

let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Moment, subtype: .Any, options: fetchOptions)

if let first_Obj:AnyObject = collection.firstObject{
//found the album
self.assetCollection = first_Obj as! PHAssetCollection
}
}

override func viewWillAppear(animated: Bool) {
// Get size of the collectionView cell for thumbnail image
if let layout = self.collectionView!.collectionViewLayout as? UICollectionViewFlowLayout{
let cellSize = layout.itemSize

self.assetThumbnailSize = CGSizeMake(cellSize.width, cellSize.height)
}

//fetch the photos from collection
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)

self.collectionView!.reloadData()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "selectedPhoto(s)"){

if let controller: SelectedPhoto = segue.destinationViewController as? SelectedPhoto{

if let cell = sender as? PhotoThumbnail {
if let indexPath: NSIndexPath = self.collectionView!.indexPathForCell(cell){
controller.index = indexPath.item
controller.photosAsset = self.photosAsset
controller.assetCollection = self.assetCollection
}
}

}
}
}


// MARK: UICollectionViewDataSource

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}


override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
var count: Int = 0

if(self.photosAsset != nil){
count = self.photosAsset.count
}

return count;
}


override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: PhotoThumbnail = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! PhotoThumbnail

//Modify the cell
let asset: PHAsset = self.photosAsset[indexPath.item] as! PHAsset

PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: self.assetThumbnailSize, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
cell.setThumbnailImage(image)
}
})

return cell
}

// MARK: - UICollectionViewDelegateFlowLayout methods
func collectionView(collectinView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 4
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1
}

// UIImagePickerControllerDelegate Methods
func imagePickerControllerDidCancel(picker: UIImagePickerController){
picker.dismissViewControllerAnimated(true, completion: nil)
}

// MARK: UICollectionViewDelegate

/*
// Uncomment this method to specify if the specified item should be selected
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
*/


// Uncomment these methods to specify if an action menu should be displayed for the specified item, and react to actions performed on the item
override func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}

override func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return false
}

override func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) {

self.dismissViewControllerAnimated(false, completion: nil)

}


}

Here's my code for the second source file (2): PhotoThumbnail.swift:

import UIKit


class PhotoThumbnail: UICollectionViewCell {

@IBOutlet weak var thumbNail: UIImageView!

func setThumbnailImage(thumbNailImage: UIImage) {
self.thumbNail.image = thumbNailImage
}

}


The Problem: For some reason, I am unable to load all the images from the Photos Library with 8 columns and I want to load 4 columns of each photo from the photo library. If anyone could help me out or even give me tutorials for something likes this, that would be greatly appreciated! Thanks in advanced haha.

Answer

I assume the reason of your problem is these lines of your code:

let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Moment, subtype: .Any, options: fetchOptions)

if let first_Obj:AnyObject = collection.firstObject{
    //found the album
    self.assetCollection = first_Obj as! PHAssetCollection
}

The first object of fetch result is not an album, it's a moment (a photo group). Check the documentation:

PHAssetCollectionTypeMoment. A moment in the Photos app. The Photos app automatically creates moments to group assets by time and location.

If you want to show photos in a first album, you just need to replace .Moment with .Album. If you want to show all the photos, you need to process all objects in PHFetchResult, not just first of them.

Comments