Post

UIKit - 코드로 Picker, Gesture 설정하기

UIKit - 코드로 Picker, Gesture 설정하기

코드로 Picker, Gesture 설정하기

예시

ViewController.swift

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import UIKit
import PhotosUI // PickerView를 사용하기 위해 import

class ViewController: UIViewController {

    private let imageView: UIImageView = {
        let imageView = UIImageView()
       
        imageView.backgroundColor = .systemGray5
        imageView.tintColor = .black
        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        
        return imageView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        makeUI()
        setGesture()
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        imageView.layer.cornerRadius = imageView.frame.width / 2.0
        imageView.clipsToBounds = true
    }
    
    func makeUI(){
        view.addSubview(imageView)
        
        NSLayoutConstraint.activate([
            imageView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            imageView.heightAnchor.constraint(equalToConstant: 200),
            imageView.widthAnchor.constraint(equalToConstant: 200)
        ])
    }
    
    func setGesture(){
        // 제스처 설정
        let gesture = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
        imageView.addGestureRecognizer(gesture)
        
        // 사용자 터치 이벤트 활성화
        imageView.isUserInteractionEnabled = true
        
    }
    
    @objc func imageViewTapped(){
        print(#function)
        
        // Picker 설정
        var configuration = PHPickerConfiguration()
        
        // 사진 선택 가능 수
        configuration.selectionLimit = 0
        
        // 이미지만 선택할 수 있도록 필터링
        configuration.filter = .images
        
        // Picker 생성
        let picker = PHPickerViewController(configuration: configuration)
        
        // Picker Delegate 설정
        picker.delegate = self
        
        // Picker 띄우기
        present(picker, animated: true)
    }
}

// Picker 동작을 처리하기 위한 Delegate 프로토콜 구현
extension ViewController: PHPickerViewControllerDelegate{
    
    // 사진을 선택했을 때 실행
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        // Picker 닫기
        picker.dismiss(animated: true)
        
        // results: 사용자가 선택한 사진 배열
        // first: results 배열 중 첫번째 요소를 가져옴
        // itemProvider: 선택한 사진 데이터를 실제 이미지 객체로 변환하는 역할
        let itemProvider = results.first?.itemProvider
        
        // 선택한 데이터가 UIImage로 변환 가능한지 확인
        if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self){
            // loadObject: 실제 객체(UIImage 등)로 변환해줌
            itemProvider.loadObject(ofClass: UIImage.self){ (image, error) in
                
                // loadObject는 백그라운드에서 실행되는데, UI 업데이트는 메인 쓰레드에서 해야하기 때문에 DispatchQueue 사용
                DispatchQueue.main.async{
                    self.imageView.image = image as? UIImage
                }
            }
        }else{
            print("이미지 로드가 정상적으로 처리되지 않음.")
        }
    }
}

위 예시 코드를 분석해보겠음.

1
import PhotosUI // PickerView를 사용하기 위해 import

Picker를 사용하기 위해서는 PhotosUIimport 해야함.

1
2
3
4
5
6
7
8
9
10
11
12
13
...

    func setGesture(){
        // 제스처 설정
        let gesture = UITapGestureRecognizer(target: self, action: #selector(imageViewTapped))
        imageView.addGestureRecognizer(gesture)
        
        // 사용자 터치 이벤트 활성화
        imageView.isUserInteractionEnabled = true
        
    }

...

imageView에 제스처를 설정하는 코드로, imageView는 기본적으로 터치같은 제스처 동작에 대한 처리가 되어있지 않기 때문에 제스처를 설정해줘야함.

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
...

    @objc func imageViewTapped(){
        print(#function)
        
        // Picker 설정
        var configuration = PHPickerConfiguration()
        
        // 사진 선택 가능 수
        configuration.selectionLimit = 0
        
        // 이미지만 선택할 수 있도록 필터링
        configuration.filter = .images
        
        // Picker 생성
        let picker = PHPickerViewController(configuration: configuration)
        
        // Picker Delegate 설정
        picker.delegate = self
        
        // Picker 띄우기
        present(picker, animated: true)
    }

...

imageView에 터치 제스처가 일어나면 실행되는 함수로, Picker를 설정하고 띄워줌.

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
// Picker 동작을 처리하기 위한 Delegate 프로토콜 구현
extension ViewController: PHPickerViewControllerDelegate{
    
    // 사진을 선택했을 때 실행
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        // Picker 닫기
        picker.dismiss(animated: true)
        
        // results: 사용자가 선택한 사진 배열
        // first: results 배열 중 첫번째 요소를 가져옴
        // itemProvider: 선택한 사진 데이터를 실제 이미지 객체로 변환하는 역할
        let itemProvider = results.first?.itemProvider
        
        // 선택한 데이터가 UIImage로 변환 가능한지 확인
        if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self){
            // loadObject: 실제 객체(UIImage 등)로 변환해줌
            itemProvider.loadObject(ofClass: UIImage.self){ (image, error) in
                
                // loadObject는 백그라운드에서 실행되는데, UI 업데이트는 메인 쓰레드에서 해야하기 때문에 DispatchQueue 사용
                DispatchQueue.main.async{
                    self.imageView.image = image as? UIImage
                }
            }
        }else{
            print("이미지 로드가 정상적으로 처리되지 않음.")
        }
    }
}

Picker에서 이미지를 선택한 후 동작을 처리하기 위해 Delegate 프로토콜을 구현함.

결과

image

This post is licensed under CC BY 4.0 by the author.