###### tags: `第14屆IT邦鐵人賽文章`
# 【在 iOS 開發路上的大小事2-Day12】PhotoKit 好像很好玩 (1)
## 前情提要 1
Apple 處理照片的 Framework 在 iOS 8 以前是使用 AssetsLibrary,
而在 iOS 8 推出後,Apple 推出了 PhotoKit 這個全新照片框架來取代 AssetsLibrary
所以今天要來介紹的就是 PhotoKit 這個照片框架!
![PhotoKit](https://docs-assets.developer.apple.com/published/b57f722288/rendered2x-1655840094.png)
▲ 圖取自 Apple
## 前情提要 2
會想要介紹 PhotoKit 是因為我的照片有點多 (大概也就 2xxxx 張而已啦),
前陣子在用內建的照片 App 時,有時候收藏照片 A,以前的照片 B 就會自己被改成未收藏,
(雖然那時候,好像發現是 Google 相簿的 bug 造成的)
要尋找未收藏的照片會蠻辛苦的,加上內建的只有篩選已收藏的功能,沒有篩選未收藏的功能
所以就只好打開 App Store 看有沒有具有這種功能的 App 可以用
## 前情提要 3
但身為 iOS App 開發者,遇到這個問題,當然是要自己寫可以解決問題的 App 來解決 (哈)
所以,就有了介紹 PhotoKit 的契機啦~
(這裡主要是會以 App 內有用到的來介紹,
其餘的可能就要自行查看 [Apple Developer Documentation](https://developer.apple.com/documentation/photokit))
## 使用 PhotoKit 的前置動作
首先,因為我們會需要存取手機內的照片,所以要先在 info.plist 裡面新增存取照片的權限
```Privacy - Photo Library Usage Description```,不然 App 一 Build 起來,就會炸給你看喔~
![](https://i.imgur.com/2fXVSAh.png)
## 如何取得相簿內的影像
### 首先,我們先宣告一些變數
```swift
// Photos 變數宣告
var allPhotos: PHFetchResult<PHAsset>!
let allPhotosOptions = PHFetchOptions() // 創建 PHFetchOptions 實例
let photosImageRequestOptions = PHImageRequestOptions()
let photoCacheImageManager = PHCachingImageManager() // 創建 PHCachingImageManager 實例
var thumbnailSize: CGSize! // 縮圖大小
```
上述有用到的 PhotoKit 型別說明 ↓
```swift
PHFetchResult // 發出影像抓取請求後取得的資源
PHAsset // 影像拍攝當下的資訊
PHFetchOptions // 影像抓取選項、篩選、排序等
PHImageRequestOptions // 影像抓取請求選項
PHCachingImageManager // 快取影像管理,提供縮圖、原圖等
```
### 確認照片存取權限
確認照片存取權限的方式有兩種
1. 單純查詢照片存取權限狀態
2. 查詢照片存取權限後,做出對應狀態的處理方式
這兩種查詢方式,分別對應到下面這幾個 Function
```swift
// 取得照片存取權限狀態
@available(iOS 14, *)
open class func authorizationStatus(for accessLevel: PHAccessLevel) -> PHAuthorizationStatus
// 查詢照片存取權限後,做出對應狀態的處理方式
@available(iOS 14, *)
open class func requestAuthorization(for accessLevel: PHAccessLevel, handler: @escaping (PHAuthorizationStatus) -> Void)
// 查詢照片存取權限後,做出對應狀態的處理方式 (await/async)
@available(iOS 14, *)
open class func requestAuthorization(for accessLevel: PHAccessLevel) async -> PHAuthorizationStatus
```
而照片存取權限也是有存取層級,像是可讀可寫、只能新增
```swift
@available(iOS 14, iOS 8, *)
public enum PHAccessLevel : Int {
@available(iOS 8, *)
case addOnly = 1 // 只允許新增
@available(iOS 8, *)
case readWrite = 2 // 允許讀寫
}
```
### 取得照片存取權限
這邊是使用第二種方式來查詢照片存取權限,查詢的 Sample Code 如下
await/async 的 Sample Code 也是大同小異,這邊就不放了
```swift
PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
if (status == .authorized) {
print("App can access User's Photos")
} else {
print("App can't access User's Photos")
}
}
```
上面 Closure 內的變數 status,型別為 ```enum PHAuthorizationStatus : Int```
```swift
@available(iOS 8, iOS 8, *)
public enum PHAuthorizationStatus : Int {
@available(iOS 8, *)
case notDetermined = 0 // 使用者尚未授權 App 是否可以存取照片
@available(iOS 8, *)
case restricted = 1 // 此 App 沒有權限存取照片
@available(iOS 8, *)
case denied = 2 // 使用者已拒絕 App 存取照片
@available(iOS 8, *)
case authorized = 3 // 使用者已授權 App 可以完整存取照片
@available(iOS 14, *)
case limited = 4 // 使用者授權 App 可以存取使用者在相簿內所選取到的照片
}
```
下一篇,再來繼續介紹 PHFetchOptions、PHPhotoLibraryChangeObserver、PHImageManager~
## 參考資料
> https://developer.apple.com/documentation/photokit
> https://www.jianshu.com/p/3ac116ffffcc
> https://www.jianshu.com/p/c5fe835bb0fb
> https://juejin.cn/post/6985128108965756936
> https://www.jianshu.com/p/78960c4fd99d
> https://www.jianshu.com/p/0ff787121ebc
> https://www.jianshu.com/p/56ffe8583eaa