사진첩에서 사진을 가져오고 삭제해보기(실습)
08 Mar 2020 | iOS개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
사진첩에서 사진 가져오기
import UIKit
import Photos
class ViewController: UIViewController, UITableViewDataSource {
// 사진 목록을 테이블뷰에 보여줄 것
@IBOutlet weak var tableView: UITableView!
var fetchResult: PHFetchResult<PHAsset>!
// 가져온 에셋을 가지고 이미지를 로드해옴
let imageManager: PHCachingImageManager = PHCachingImageManager()
let cellIdentifier: String = "cell"
func requestCollection() {
// 사진찍으면 사진이 저장되는 카메라롤의 컬렉션을 가져옴
let cameraRoll: PHFetchResult<PHAssetCollection> = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)
guard let cameraRollColletction = cameraRoll.firstObject else {
return
}
let fetchOptions = PHFetchOptions()
// 최신순으로 사진을 sort
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
// 그 결과를 fetchResult라는 프로퍼티로 가져옴
self.fetchResult = PHAsset.fetchAssets(in: cameraRollColletction, options: fetchOptions)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
print("접근 허가됨")
self.requestCollection()
self.tableView.reloadData()
case .denied:
print("접근 불허")
case .notDetermined:
print("아직 응답하지 않음")
PHPhotoLibrary.requestAuthorization({ (status) in
switch status {
case .authorized:
print("사용자가 허용함")
self.requestCollection()
self.tableView.reloadData()
case .denied:
print("사용자가 불허함")
default: break
}
})
case .restricted:
print("접근 제한")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.fetchResult?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// cell에 이미지를 하나씩 넣어줌
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: self.cellIdentifier, for: indexPath)
// asset은 fetchresult에서 index에 해당
let asset: PHAsset = fetchResult.object(at: indexPath.row)
// imageManager를 통해 실질적인 이미지를 요청
imageManager.requestImage(for: asset, targetSize: CGSize(width: 30, height: 30), contentMode: .aspectFill, options: nil, resultHandler: { image, _ in cell.imageView?.image = image})
return cell
}
}
이렇게 코드를 진행하게 되면 에러가 발생할 것이다.
reloadData는 메인 쓰레드에서만 동작해야한다. » operation queue 사용
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
print("접근 허가됨")
self.requestCollection()
self.tableView.reloadData()
case .denied:
print("접근 불허")
case .notDetermined:
print("아직 응답하지 않음")
PHPhotoLibrary.requestAuthorization({ (status) in
switch status {
case .authorized:
print("사용자가 허용함")
self.requestCollection()
OperationQueue.main.addOperation {
self.tableView.reloadData()
}
case .denied:
print("사용자가 불허함")
default: break
}
})
case .restricted:
print("접근 제한")
}
}
사진첩에서 사진 삭제하기
import UIKit
import Photos
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, PHPhotoLibraryChangeObserver {
// PHphotoobserver는 library에 변화가 생기면 감지를 하는 프로토콜
// 사진 목록을 테이블뷰에 보여줄 것
@IBOutlet weak var tableView: UITableView!
var fetchResult: PHFetchResult<PHAsset>!
// 가져온 에셋을 가지고 이미지를 로드해옴
let imageManager: PHCachingImageManager = PHCachingImageManager()
let cellIdentifier: String = "cell"
func requestCollection() {
// 사진찍으면 사진이 저장되는 카메라롤의 컬렉션을 가져옴
let cameraRoll: PHFetchResult<PHAssetCollection> = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)
guard let cameraRollColletction = cameraRoll.firstObject else {
return
}
let fetchOptions = PHFetchOptions()
// 최신순으로 사진을 sort
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
// 그 결과를 fetchResult라는 프로퍼티로 가져옴
self.fetchResult = PHAsset.fetchAssets(in: cameraRollColletction, options: fetchOptions)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let photoAuthorizationStatus = PHPhotoLibrary.authorizationStatus()
switch photoAuthorizationStatus {
case .authorized:
print("접근 허가됨")
self.requestCollection()
self.tableView.reloadData()
case .denied:
print("접근 불허")
case .notDetermined:
print("아직 응답하지 않음")
PHPhotoLibrary.requestAuthorization({ (status) in
switch status {
case .authorized:
print("사용자가 허용함")
self.requestCollection()
OperationQueue.main.addOperation {
self.tableView.reloadData()
}
case .denied:
print("사용자가 불허함")
default: break
}
})
case .restricted:
print("접근 제한")
}
// 아래 한줄을 써줌으로써 photoLibrary가 변화될때마다 delegate메서드가 호출됨
PHPhotoLibrary.shared().register(self)
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { // row를 편집할수 있게 해주는 메서드, tableview row를 밀어서 삭제하는 행위를 가능하게 함
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
// 삭제 모드로 들어왔을때(편집을 하려할때)
if editingStyle == .delete { // 삭제라면 asset을 가지고 delete를 하면
let asset: PHAsset = self.fetchResult[indexPath.row]
PHPhotoLibrary.shared().performChanges({PHAssetChangeRequest.deleteAssets([asset] as NSArray)}, completionHandler: nil)
// 실제 삭제를 하게되면 나오게 되는 팝업창
}
}
func photoLibraryDidChange(_ changeInstance: PHChange) {
// observer 프로토콜을 따른 메서드
guard let changes = changeInstance.changeDetails(for: fetchResult) else {
return
}
// 어떤게 바꼈는지
fetchResult = changes.fetchResultAfterChanges
// 바꼈다면 tableview를 다시 불러달라
OperationQueue.main.addOperation {
self.tableView.reloadSections(IndexSet(0...0), with: .automatic)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.fetchResult?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// cell에 이미지를 하나씩 넣어줌
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: self.cellIdentifier, for: indexPath)
// asset은 fetchresult에서 index에 해당
let asset: PHAsset = fetchResult.object(at: indexPath.row)
// imageManager를 통해 실질적인 이미지를 요청
imageManager.requestImage(for: asset, targetSize: CGSize(width: 30, height: 30), contentMode: .aspectFill, options: nil, resultHandler: { image, _ in cell.imageView?.image = image})
return cell
}
}