为什么在应用程序的初始启动期间不显示照片?
Why don't the photos appear during the initial launch of the app?
我实现了一个 viewController
,其中包含一个 collectionView
,用于保存用户相册中保存在其 phone 中的照片。在应用程序请求用户访问其照片的权限后首次启动应用程序时,照片不会显示在 collectionView
中。但是在退出应用程序并重新启动照片后,照片会正常显示。
下面是有问题viewController
的代码
import UIKit
import Photos
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {
var imageArray:[UIImage] = [UIImage]()
var collectionView:UICollectionView! = {
let layout = UICollectionViewFlowLayout()
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
layout.scrollDirection = .vertical
let CV = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: layout)
CV.translatesAutoresizingMaskIntoConstraints = false
return CV
}()
var fetchResult: PHFetchResult<PHAsset> = PHFetchResult()
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
self.collectionView.dataSource = self
collectionView.register(customPhotoCell.self, forCellWithReuseIdentifier: "Cell")
self.view.addSubview(collectionView)
setUpLayout()
fetchAssets()
}
func setUpLayout(){
collectionView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true
collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
}
func fetchAssets(){
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return fetchResult.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! customPhotoCell
let imageView = cell.imgView
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
PHImageManager.default().requestImage(for: fetchResult.object(at: indexPath.item) , targetSize: CGSize(width: 200,height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image,error in
if let error = error{
print(error)
}
self.imageArray.append(image!)
imageView.image = image!
})
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = self.view.bounds.width/3 - 1
return CGSize(width: width, height: width)
}
}
class customPhotoCell:UICollectionViewCell{
var imgView:UIImageView = {
let imgV = UIImageView()
imgV.backgroundColor = .orange
imgV.translatesAutoresizingMaskIntoConstraints = false
return imgV
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(imgView)
imgView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
imgView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
imgView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
imgView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIImageView{
func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize) {
let options = PHImageRequestOptions()
options.version = .original
PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: contentMode, options: options) { image, _ in
guard let image = image else { return }
switch contentMode {
case .aspectFill:
self.contentMode = .scaleAspectFill
case .aspectFit:
self.contentMode = .scaleAspectFit
}
self.image = image
}
}
}
extension UIImage{
func resizeImageWith() -> UIImage {
let aspectRatio = CGFloat(self.size.width / self.size.height)
let newWidth = UIScreen.main.bounds.width
let newSize = CGSize(width: newWidth, height: newWidth/aspectRatio)
UIGraphicsBeginImageContextWithOptions(newSize, true, 0)
self.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
在 viewDidAppear
中重新加载您的 collectionView,在应用请求用户许可后,viewDidAppear
方法将被调用。
colllectionView.reloadData()
首先检查您是否有权限。如果您仅被授权,则初始化 fetchResult 并重新加载 collectionView。
func checkPhotoLibraryPermission() {
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
self.fetchAssets()
self.cv.reloadData()
case .denied, .restricted : break
//handle denied status
case .notDetermined:
// ask for permissions
PHPhotoLibrary.requestAuthorization() { status in
switch status {
case .authorized:
DispatchQueue.main.async {
self.fetchAssets()
self.cv.reloadData()
}
// as above
case .denied, .restricted: break
// as above
case .notDetermined: break
// won't happen but still
}
}
}
在 viewDidLoad()
而不是 fetchAssets()
中调用此方法。希望这有帮助。
我实现了一个 viewController
,其中包含一个 collectionView
,用于保存用户相册中保存在其 phone 中的照片。在应用程序请求用户访问其照片的权限后首次启动应用程序时,照片不会显示在 collectionView
中。但是在退出应用程序并重新启动照片后,照片会正常显示。
下面是有问题viewController
的代码
import UIKit
import Photos
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource {
var imageArray:[UIImage] = [UIImage]()
var collectionView:UICollectionView! = {
let layout = UICollectionViewFlowLayout()
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
layout.scrollDirection = .vertical
let CV = UICollectionView(frame: UIScreen.main.bounds, collectionViewLayout: layout)
CV.translatesAutoresizingMaskIntoConstraints = false
return CV
}()
var fetchResult: PHFetchResult<PHAsset> = PHFetchResult()
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
self.collectionView.dataSource = self
collectionView.register(customPhotoCell.self, forCellWithReuseIdentifier: "Cell")
self.view.addSubview(collectionView)
setUpLayout()
fetchAssets()
}
func setUpLayout(){
collectionView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true
collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0).isActive = true
collectionView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0).isActive = true
collectionView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
}
func fetchAssets(){
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return fetchResult.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! customPhotoCell
let imageView = cell.imgView
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
PHImageManager.default().requestImage(for: fetchResult.object(at: indexPath.item) , targetSize: CGSize(width: 200,height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image,error in
if let error = error{
print(error)
}
self.imageArray.append(image!)
imageView.image = image!
})
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = self.view.bounds.width/3 - 1
return CGSize(width: width, height: width)
}
}
class customPhotoCell:UICollectionViewCell{
var imgView:UIImageView = {
let imgV = UIImageView()
imgV.backgroundColor = .orange
imgV.translatesAutoresizingMaskIntoConstraints = false
return imgV
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(imgView)
imgView.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
imgView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
imgView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
imgView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIImageView{
func fetchImage(asset: PHAsset, contentMode: PHImageContentMode, targetSize: CGSize) {
let options = PHImageRequestOptions()
options.version = .original
PHImageManager.default().requestImage(for: asset, targetSize: targetSize, contentMode: contentMode, options: options) { image, _ in
guard let image = image else { return }
switch contentMode {
case .aspectFill:
self.contentMode = .scaleAspectFill
case .aspectFit:
self.contentMode = .scaleAspectFit
}
self.image = image
}
}
}
extension UIImage{
func resizeImageWith() -> UIImage {
let aspectRatio = CGFloat(self.size.width / self.size.height)
let newWidth = UIScreen.main.bounds.width
let newSize = CGSize(width: newWidth, height: newWidth/aspectRatio)
UIGraphicsBeginImageContextWithOptions(newSize, true, 0)
self.draw(in: CGRect(origin: CGPoint(x: 0, y: 0), size: newSize))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
在 viewDidAppear
中重新加载您的 collectionView,在应用请求用户许可后,viewDidAppear
方法将被调用。
colllectionView.reloadData()
首先检查您是否有权限。如果您仅被授权,则初始化 fetchResult 并重新加载 collectionView。
func checkPhotoLibraryPermission() {
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
self.fetchAssets()
self.cv.reloadData()
case .denied, .restricted : break
//handle denied status
case .notDetermined:
// ask for permissions
PHPhotoLibrary.requestAuthorization() { status in
switch status {
case .authorized:
DispatchQueue.main.async {
self.fetchAssets()
self.cv.reloadData()
}
// as above
case .denied, .restricted: break
// as above
case .notDetermined: break
// won't happen but still
}
}
}
在 viewDidLoad()
而不是 fetchAssets()
中调用此方法。希望这有帮助。