8

This question has been asked before but there were no answers for Swift 3. I am looking for the same solution which I am stuck for the past 3 weeks.

I have done my research and watched numerous Youtube videos about loading images from Photos/Camera Roll into the app using UIImagePickerController but I want to access the photos without user actions.

I want to read a series of photos from camera roll and put them in a photo slide to show them one by one. How can I access these photos without UIImagePickerController?

Spiral1ng
  • 313
  • 1
  • 7
  • 16
  • Did you tried using Photos Framework you can access photos from camera Roll or from any album without making use of imagePicker – iOS Geek Jul 03 '17 at 03:04
  • https://developer.apple.com/library/content/samplecode/UsingPhotosFramework/Introduction/Intro.html Check this Sample Code by Apple – iOS Geek Jul 03 '17 at 03:07
  • Sorry if i sound noob, I have downloading it and was not able to run in my xcode 8.3. And I have no idea where to download xcode 9. – Spiral1ng Jul 03 '17 at 03:14
  • @Spiral1ng Check my answer. Xcode 9 is in Beta currently. You can continue to do the things on Xcode 8.3 – Rajan Maheshwari Jul 03 '17 at 03:16

1 Answers1

23

You can use the Photos framework to fetch the photos from CameraRoll/Photos.

Here is the version of Swift 3 code.

Import the photos framework

import Photos

//Array of PHAsset type for storing photos
var images = [PHAsset]()

Use this function to fetch the photos, somewhere in viewDidLoad or on your action wherever you want to fetch the photos.

func getImages() {
    let assets = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: nil)
    assets.enumerateObjects({ (object, count, stop) in
       // self.cameraAssets.add(object)
        self.images.append(object)
    })

    //In order to get latest image first, we just reverse the array
    self.images.reverse() 

    // To show photos, I have taken a UICollectionView       
    self.photosCollectionView.reloadData()
}

Rest are UICollectionView Datasource and Delegates. See the cellForItem datasource method on How to show the image.

 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
       return images.count
    }

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as! PhotoCollectionViewCell
    let asset = images[indexPath.row]
    let manager = PHImageManager.default()
    if cell.tag != 0 {
            manager.cancelImageRequest(PHImageRequestID(cell.tag))
        }
    cell.tag = Int(manager.requestImage(for: asset,
                                            targetSize: CGSize(width: 120.0, height: 120.0),
                                            contentMode: .aspectFill,
                                            options: nil) { (result, _) in
                                                cell.photoImageView?.image = result
        })
    return cell
}

Adjust the below delegates as per your need.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = self.view.frame.width * 0.32
    let height = self.view.frame.height * 0.179910045
    return CGSize(width: width, height: height)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 2.5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

Make sure to keep the photos permission ON. If you click Don't Allow, then you have to manage the authorization too using PHPhotoLibrary.authorizationStatus()

You can read more about Photos framework.

Rajan Maheshwari
  • 14,465
  • 6
  • 64
  • 98
  • 1
    "Use this function to fetch the photos, somewhere in viewDidLoad or on your action wherever you want to fetch the photos." Just make sure that you do the fetch on a background thread and then reload the view on the main thread! – NRitH Jul 03 '17 at 03:27
  • @NRitH Exactly. – Rajan Maheshwari Jul 03 '17 at 03:36
  • Many thanks for the reply. The code compiled without any error. But I see a blank screen without any images loaded into the app (The permission prompt to access Photos did appear). I have added a UICollectionView called photosCollectionView. Am I supposed to see the photos inside this UICollectionView? Sorry for the questions. – Spiral1ng Jul 03 '17 at 04:23
  • Just allow the permission and then you will get an array of images which you can use in collection view, table view or wherever you want – Rajan Maheshwari Jul 03 '17 at 05:44
  • @Spiral1ng did it helped you? – Rajan Maheshwari Jul 06 '17 at 06:59
  • enumerateObjects performs in an undefined order, so relying on its order to be correct to then reverse the array probably isn't reliable. You will likely need to sort by the creationDate property of PHPhoto – aronspring Oct 24 '18 at 13:25