Reputation: 43
When I open my application it asks me for permission to access my photos. That is all all right. But after accepting, the screen turns black and shows no photos and in my console it says that it has found no photos. Although I have photos on my device.
import UIKit
import Photos
class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var imageArray = [UIImage]()
override func viewDidLoad() {
grabPhotos()
}
func grabPhotos(){
let imgManager = PHImageManager.defaultManager()
let requestOptions = PHImageRequestOptions()
requestOptions.synchronous = true
requestOptions.deliveryMode = .HighQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key:"CreationDate" , ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: fetchOptions){
if fetchResult.count > 0 {
for i in 0..<fetchResult.count{
imgManager.requestImageForAsset(fetchResult.objectAtIndex(i) as! PHAsset, targetSize: CGSize(width: 200, height: 200), contentMode: .AspectFill, options: requestOptions, resultHandler: {
image, error in
self.imageArray.append(image!)
})
}
}
else{
print("You have got not photos!")
self.collectionView?.reloadData()
}
}
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let width = collectionView.frame.width / 3 - 1
return CGSize(width: width, height: width)
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1.0
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1.0
}
}
Upvotes: 0
Views: 1265
Reputation: 126127
Most likely the problem here is that you're asking for assets only once. The first time you ask, you get nothing. When you call PHAsset.fetchAssetsWithMediaType
, it does two things at the same time: It asks the user for authorization, and because authorization hasn't been granted yet (the authorization prompt is still on screen), it returns an empty fetch result. (And because the fetch result is empty, you can't
If that's the problem, you should see a non-empty fetch result the second time you run your app (because authorization is a one-time thing and persists across launches).
There are a few ways to deal with this...
One is simply to request authorization directly first using requestAuthorization()
and fetch assets only after that call's completion handler fires (with a positive result).
Another is to register()
your view controller (or some other controller class of yours) as an observer of the Photos library before performing a fetch. Your first fetch before authorization still returns an empty result, but as soon as the user has authorized your app your observer gets a photoLibraryDidChange()
call from which you can access the full, "real" fetch results.
Beyond that, there are some other things you're doing that aren't best practice here...
You're requesting images from the PHImageManager
for every asset in the library, regardless of whether the user is going to see them. Consider the case of someone whose iCloud Photo Library contains tens of thousands of assets — only the first 30 or so are going to fit on your collection view at once, and the user may never scroll all the way to the end, but you're still fetching thumbnails for Every Image Ever. (And in the case of iCloud assets not on the local device, trigging network activity for lots of thumbnails the user might never see.)
You're getting thumbnails from PHImageManager
synchronously and sequentially. Once you get the authorization issue dealt with, your app will probably crash because your for i in 0..<fetchResult.count { imgManager.requestImageForAsset
loop blocks the main thread for too long.
Apple provides canonical example code that demonstrates how to use the Photos app to do things like displaying a collection view full of thumbnails. Take a look at AssetGridViewController.swift
in that project to see some of the things they're doing:
PHCachingImageManager
to prefetch batches of thumbnails based on the visible area of a collection viewPHPhotoLibraryObserver
to react to changes in a fetch result, including animated collection view updatesUpvotes: 3
Reputation: 12910
1) Subclass a UICollectionViewCell:
import ...
//put this e.g. to the top of your swift file, right after import statements
class PhotoViewCell: UICollectionViewCell {
@IBOutlet weak var myImageView: UIImageView!
}
2) Create a prototype for you cell:
2.1 design it (you may have done before)
2.2 enter an identifier
2.3 enter a class
2.4 CTRL drag from storyboard: from the cell's imageView to the @IBOutlet line (from the step 1)
3) Update your cellForItem method:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! PhotoViewCell {
cell.myImageView.image = imageArray[indexPath.row]
return cell
}
Upvotes: 0
Reputation: 50
use a class for cell , put imageview in your cell make it an outlet
now write this
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! 'your class name for cell'
cell.Image.image = imageArray[indexPath.row]
return cell
}
Upvotes: -1