UIImagePickerController
사진을 찍고, 동영상을 녹화하고 사용자의 미디어라이브러리 항목을 선택하기위한 VC임
뭔소린지 추상적이라서 더 자세히 읽어보도록 하자
Declaration @MainActor class UIImagePickerController : UINavigationController
일단 네비게이션컨트롤러를 상속받고있는 클래스임…ㅇㅎ
[개요]
- UIImagePickerController는 사용자의 상호작용을 하고 이러한 결과를 대리자개체에 전달한다.
- 이미지 선택하는 Controller의 역할과 모양은 presentation하기이전에 할당한 자원 타입에 따라 다르다…? => 설정 하기에따라 모양이 다르다는소리같음…
- UIImagePickerController.SourceType.camera의 sourceType은 새로운 사진이나 영상을 찍기위한 기능이다.
- UIImagePickerController.SourceType.PhotoLibrary또는 .savedPhotosAlbum은 저장된 사진과 동영상중에서 선택하기위한 기능이다.
기본컨트롤이포함된 이미지 선택하는 Controller를 사용하려면 이와같은 단계를 거치면된다.
- 자원으로부터 컨텐츠를 선택할 수 있는 자격이 있는지 장치를 검사한다.
- isSourceTypeAvailable클래스 메서드를 호출하여 UIImagePickerController.SOurceType열거에서 상수를 제공하여 이를 수행할 수 있다.
- availableMediaTypes(for:)클래스메서드를 호출하여 사용중인 소스에 사용할 수 있는 미디어 유형을 확인합니다.
- 이를 통해 동영상 촬영에 사용할 수 있는 카메라와 정지 이미지에만 사용할 수 있는 카메라를 구분할 수 있습니다.
- mediaTypes속성을 설정해 UIImagePickerController에 사용가능하게 하려는 mediaType (stillImages, movies, both)에 따라 UI를 조정하도록 설정할 수 있습니다.
- iPhone or iPod touch에서 화면을 넘길때 modal()로 present하여 화면을 수행합니다.
- 사용자가 찍은 사진 이나 저장된 이미지 또는 동영상을 선택하기위해 탭버튼을 누르거나 또는 취소버튼을 누르는 경우에 IPC는 delegate를 사용합니다.
- 이전에 저장한 이미지이거나 새로캡처한 데이터를 사용할 수 있음
IMPORTANT
UIIMAGEPICKERCONTROLLER클래스는 세로모드만 지원합니다. 이 클래스는 있는 그대로 사용하기위한것이며 서브클래싱을 지원하지않습니다. 그래서 이 클래스의 보기계층 구조는 비공개이며 한 가지예외를 제외하고는 수정해서는 안됩니다. cameraOverlayView 프로퍼티 뷰를 커스텀하거나 사용하겨 추가정보를 제공하는 카메라 인터페이스와 코드간의 상호작용을 관리할 수 있습니다.
delegate 객체를 지원합니다.
추가적으로 영상찍는거나 라이브사진작업 그리고 플래시모드 등의 작업에관한내용은 현재 작업하지는 않을것같아 나중에 필요할때 참고해보자
UIImagePicker사용해서 album에서 사진 가져오기
- Info에서 이 두가지 기능을 추가한다.
설정방법: (info파일 클릭 -> Information Property List 오른쪽 +버튼 클릭 -> 아래 내용을 입력하면 목록이나옴 -> 선택하면됨)
Privacy - Camera Usage Description (= 카메라 사용을 허용해주세요라고 설정하는것)
Privacy - PhotoLibraryAddUsageDescription (= 사진앨범 가져오게 허용해주세요라고 설정하는것) - 뷰컨에 두 가지를 상속해준다.
- UIImagePickerControllerDelegate(= 이미지를 선택하고 카메라를 찍었을때 다양한 동작을 도와줌)
- UINavigationControllerDelegate(=앨범 사진을 선택했을때, 화면 전환을 네비게이션으로 이동함)
시뮬레이터는 카메라에 접근하려고 메서드를 실행하면 에러가 발생한다. 추측이지만 시뮬레이터는현재…카메라기능 지원이 안되기에 오류가 발생하는 것같음
그래서 presentAlbum()메서드만 확인해볼것이다!
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@IBOutlet var profileImageView: UIImageView!
var count = 0
override func viewDidLoad() {
super.viewDidLoad()
actionSheetAlert()
}
private func actionSheetAlert() {
DispatchQueue.main.async {
let alert = UIAlertController(title: "선택",
message: nil,
preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "취소",
style: .cancel)
let camera = UIAlertAction(title: "카메라",
style: .default) { [weak self] (_) in
self?.presentCamera()
}
let album = UIAlertAction(title: "앨범",
style: .default) { [weak self] (_) in
self?.presentAlbum()
}
alert.addAction(cancel)
alert.addAction(camera)
alert.addAction(album)
self.present(alert, animated: true, completion: nil)
}
}
// 이코드는 카메라에 접근하기위한 코드인데 시뮬레이터로 이메서드를 실행하면 에러가발생한다.. 뇌피셜이지만 실폰이아니기에 카메라자체가 없어서 그런것같다.
private func presentCamera() {
let ipc = UIImagePickerController()
ipc.sourceType = .camera
ipc.delegate = self
ipc.allowsEditing = true
ipc.cameraFlashMode = .on
present(ipc, animated: true)
}
private func presentAlbum() {
let ipc = UIImagePickerController()
ipc.sourceType = .photoLibrary
ipc.delegate = self
ipc.allowsEditing = true // 사용자편집 가능여부
present(ipc, animated: true)
}
// 기본적으로 제공하는 메서드임: 취소버튼 눌렀을때 화면을 사라지게해주는 기능
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true)
}
// 기본적으로 제공하는 메서드: 카메라나 앨범등 PickerController가 사용되거나 이미지 촬영을 하게되면 실행되는 기능
// 카메라나 앨범에서 사용하기 버튼을 눌렀을때, info에 설정에 따라서 image가 저장됩니다. 그리고 dismiss로 메모리에서 지워줘야합니다.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
dump("picker -> \(String(describing: info[UIImagePickerController.InfoKey.imageURL]))")
if self.count % 2 == 0 {
if let image = info[.editedImage] as? UIImage {
self.profileImageView.image = image
}
} else {
if let image = info[.originalImage] as? UIImage {
self.profileImageView.image = image
}
}
self.count += 1
print(self.count)
dismiss(animated: true)
actionSheetAlert()
}
}
실행화면
에러 발생 및 문제해결
- actionSheetAlert()메서드를 실행하게되면
Attempt to present UIAlertController whose view is not in the window hierarchy 이러한 에러메세지와함께
앱에서 얼럿이 보이질 않는다…
그래서 stackOverflow 에 찾아보니 DispatchQueue.main.async내에 감싸줬더니 오류해결이 되었다. 그런데 왜안되는지에대해서는 stackOverflow에 나와있지는 않는것같았다. 🤔🤔🤔
Reference
'iOS' 카테고리의 다른 글
[iOS] View Drawing Cycle (0) | 2022.06.14 |
---|---|
[iOS] multipart/form-data 형식으로 서버에 request요청하기! (0) | 2022.05.25 |
[iOS] Fetching Website Data into Memory (0) | 2022.05.23 |
[iOS] File System 공식문서 톺아보기 및 간단 정리 (0) | 2022.05.16 |
[예약] Runtime시 발생하는 관련 오류는 보라색으로 표시된다..? (0) | 2022.05.16 |