Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- uiscrollview
- Observable
- 클린 코드
- clean architecture
- ribs
- tableView
- collectionview
- Protocol
- Refactoring
- SWIFT
- 리팩토링
- ios
- 애니메이션
- Human interface guide
- combine
- UITextView
- MVVM
- rxswift
- Xcode
- 스위프트
- HIG
- UICollectionView
- 리펙터링
- Clean Code
- swift documentation
- swiftUI
- 리펙토링
- map
- uitableview
- RxCocoa
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 사진 선택 권한 (limited, presentLimitedLibraryPicker, Photos, PhotosUI, select photos) 본문
iOS 응용 (swift)
[iOS - swift] 사진 선택 권한 (limited, presentLimitedLibraryPicker, Photos, PhotosUI, select photos)
jake-kim 2023. 3. 24. 02:32
사진 선택 권한
- iOS 14+
- 사진 선택 권한을 사용자가 선태하면 limited 상태로 저장
- 사진 권한 message 문구를 위해 info.plist에 아래 내용 추가
- 실제 value에는 구체적으로 적어야 리젝 x
- 보통 사진 권한은 아래처럼 요청
- 파라미터에는 .readWrite와 .addOnly가 있는데 addOnly는 삭제가 불가능한 접근 권한이고, readWrite는 삭제가 가능한 접근 권한
private var status: PHAuthorizationStatus {
PHPhotoLibrary.authorizationStatus(for: .readWrite)
}
- status의 종류는 5가지
- limited는 사용자가 "사진 선택"을 누르고 사진을 선택하고나서 done 버튼을 누른 이후부터 limited 상태로 변경
private func printStatus() {
switch status {
case .restricted:
print("restricted")
case .denied:
print("denied")
case .authorized:
print("authorized")
case .limited:
print("limited")
case .notDetermined:
print("notDetermined")
@unknown default:
print("@unknown")
}
}
- 예제에 사용할 UI 준비
- photoButton - 사진 권한 요청
- presentMorePhotoButton - limited 상태가 될때, 사용자에게 limited 상태이니, 사진을 더 고를 수 있도록 버튼 제공
- settingButton - limited 상태가 될때, 사용자에게 limited 상태이니, 아예 모든 사진을 허용할 수 있도록 하는 버튼
import UIKit
import Photos
import PhotosUI
class ViewController: UIViewController {
private let photoButton: UIButton = {
let button = UIButton()
button.setTitle("사진", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
button.addTarget(self, action: #selector(tap), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let presentMorePhotoButton: UIButton = {
let button = UIButton()
button.setTitle("사진 더 추가하기(현재 limited 상태)", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
button.addTarget(self, action: #selector(tapMorePhoto), for: .touchUpInside)
button.isHidden = true
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let settingButton: UIButton = {
let button = UIButton()
button.setTitle("모든 사진 허용 - 설정 이동(현재 limited 상태)", for: .normal)
button.setTitleColor(.systemBlue, for: .normal)
button.setTitleColor(.blue, for: .highlighted)
button.addTarget(self, action: #selector(tapGoSetting), for: .touchUpInside)
button.isHidden = true
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(photoButton)
view.addSubview(presentMorePhotoButton)
view.addSubview(settingButton)
NSLayoutConstraint.activate([
photoButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
photoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
NSLayoutConstraint.activate([
presentMorePhotoButton.topAnchor.constraint(equalTo: photoButton.bottomAnchor, constant: 16),
presentMorePhotoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
NSLayoutConstraint.activate([
settingButton.topAnchor.constraint(equalTo: presentMorePhotoButton.bottomAnchor, constant: 16),
settingButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
])
}
...
- 공통으로 여러곳에서 사용되는 프로퍼티는 computed property로 두고 각 버튼의 탭 이벤트 정의
- tap() 메소드가 핵심 - 권한을 요청한 후에 사용자가 사진 선택 권한을 선택하고, 위로 올라온 사진첩에서 특정 사진을 선택 후 done 버튼을 누를때 아래 클로저가 실행
- delegate를 설정하여, 앞으로도 앨범에서 사진을 선택한 후 done 버튼을 눌렀을때 이벤트를 캐치하기 위함
(보통 사진이 추가되면 PHAssets같은 것으로 새로운 이미지를 로드하여 사용해야하기 때문에 델리게이트 필요)
private var status: PHAuthorizationStatus {
PHPhotoLibrary.authorizationStatus(for: .readWrite)
}
private var isLimited: Bool {
status == .limited
}
@objc private func tap() {
printStatus()
guard status == .notDetermined else { return }
PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
self.printStatus()
DispatchQueue.main.async {
self.updateButtonAssociatedLimitedStatus()
}
if self.isLimited {
PHPhotoLibrary.shared().register(self)
}
}
}
@objc private func tapMorePhoto() {
PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: self)
}
@objc private func tapGoSetting() {
guard
let url = URL(string: UIApplication.openSettingsURLString),
UIApplication.shared.canOpenURL(url)
else { return }
UIApplication.shared.open(url, completionHandler: { (success) in
print("finished")
})
}
private func printStatus() {
switch status {
case .restricted:
print("restricted")
case .denied:
print("denied")
case .authorized:
print("authorized")
case .limited:
print("limited")
case .notDetermined:
print("notDetermined")
@unknown default:
print("@unknown")
}
}
private func showPresentMorePhotoButtonIfNeeded() {
presentMorePhotoButton.isHidden = !(status == .limited)
}
private func updateButtonAssociatedLimitedStatus() {
presentMorePhotoButton.isHidden = !isLimited
settingButton.isHidden = presentMorePhotoButton.isHidden
}
- viewDidLoad에서도 이미 limited 상태이면은 바로 델리게이트 설정
- viewDidLoad에서 limited 분기문을 넣는 이유?
- PHPhotoLibrary.shared().register(self)를 호출하면 바로 권한 물어보므로 isLimited 상태일때만 delegate 설정
if isLimited {
PHPhotoLibrary.shared().register(self)
}
- delegate 구현
extension ViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
// done 버튼 누른 경우 메소드 실행
print("test>", changeInstance)
}
}
시스템에서 자동으로 호출되는 팝업
- 사진 선택 옵션을 선택하면 애플은 자동으로 앱을 다시 실행할때, 사진 선택 권한인 상태(= limited)에서 다시 사진 권한을 요청하면 아래 팝업이 노출
- 간헐적으로 아래 팝업이 안보이는 케이스가 있으므로 주의
- 비활성화 방법?
- info.plist에 아래 key로하고, value를 YES로 하면 자동으로 팝업 노출이 비활성화됨
NSPhotoLibraryAddUsageDescription
주의사항
- 권한 status를 얻는 메소드가 2가지가 있는데, 사진 선택 권한인 상태에서 파리미터가 없는 authorizationStatus()는 authorized를 리턴하므로 주의
// 현재 사용자가 사진 선택 권한을 선택한 상태
PHPhotoLibrary.authorizationStatus(for: .readWrite) // denied
PHPhotoLibrary.authorizationStatus() // authorized
* 전체 코드: https://github.com/JK0369/ExPhotoPermission_1
* 참고
https://swiftsenpai.com/development/photo-library-permission/
'iOS 응용 (swift)' 카테고리의 다른 글
Comments