๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

์‚ฌ์ง„ ์•จ๋ฒ”์—์„œ ์‚ฌ์ง„ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

์˜ค๋Š˜ ์ •๋ฆฌํ•  ๋‚ด์šฉ์€ iOS์˜ ์‚ฌ์ง„์ฒฉ์— ์ ‘๊ทผํ•ด ์‚ฌ์ง„์„ ๋ถˆ๋Ÿฌ์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋‚ด์— ํ‘œ์‹œํ•˜๋Š” ์ž‘์—…์˜ ํ๋ฆ„์ž…๋‹ˆ๋‹ค. ์ด๊ฑด ์จ๋ดค์„ ๋•Œ ์ •๋ฆฌ ์•ˆํ•˜๋ฉด ๋ฌด์กฐ๊ฑด ๊นŒ๋จน๊ณ  ๋‹ค์‹œ ๊ตฌ๊ธ€๋งํ•˜๊ณ  ์žˆ์„ ๊ฒƒ ๊ฐ™์•„์„œ ์ƒ์ƒํ•  ๋•Œ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค!

๋จผ์ € ์•„๋ž˜์™€ ๊ฐ™์ด ๊ธฐ๋ณธ์ ์ธ UI๋ฅผ ์„ธํŒ…ํ•˜๊ณ  IBOutlet์„ ์ •์˜ํ–ˆ๋Š”๋ฐ์š”, ์ด ํฌ์ŠคํŠธ์˜ ๋ชฉํ‘œ๋Š” ํ™”๋ฉด์— ๋ณด์ด๋Š” ๋…ธ๋ž€์ƒ‰ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ UIImageView์— ํ•ด๋‹น ์‚ฌ์ง„์„ ํ‘œ์‹œํ•˜๋Š” ๊ณผ์ •์„ ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค ๐ŸŽ

 

1. IBAction ์„ค์ •

๋จผ์ € ๋ฒ„ํŠผ์ด ๋ˆŒ๋ ธ์„ ๋•Œ์˜ ๋™์ž‘์„ ์ •์˜ํ•˜๊ธฐ ์œ„ํ•ด์„œ IBAction๋ถ€ํ„ฐ ์ •์˜ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋งˆ์šฐ์Šค ์šฐํด๋ฆญ์œผ๋กœ UIButton์„ ์„ ํƒํ•˜๊ณ  ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋กœ ๋“œ๋ž˜๊ทธํ•˜๋ฉด IBAction์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import UIKit 

class ViewController: UIViewController { 
	@IBOutlet weak var imageView: UIImageView! 
    @IBOutlet weak var openPhotosButton: UIButton! 
    
    override func viewDidLoad() { 
    	super.viewDidLoad() 
    } 
    
    @IBAction func openPhotosButtenPressed(_ sender: Any) { 
    } 
}

 

2. Delegate ์ฑ„ํƒํ•˜๊ธฐ

๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์ง„์„ ๋ถ€๋ฅด๊ธฐ ์œ„ํ•ด์„œ๋Š” ์‚ฌ์ง„์„ ๊ณ ๋ฅด๋Š” ํ™”๋ฉด์ธ UIImagePicker๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์— ๋‘ ๊ฐ€์ง€ delegate๋ฅผ ์ฑ„ํƒ์‹œ์ผœ์•ผํ•ฉ๋‹ˆ๋‹ค.

UIImagePickerControllerDelegate

UIImagePicker

๐Ÿ’ก A view controller that manages the system interfaces for taking pictures, recording movies, and choosing items from the user's media library.

์• ํ”Œ์˜ ๊ณต์‹๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด, UIImagePicker๋Š” ์‚ฌ์ง„/์˜์ƒ์„ ์ฐ๊ฑฐ๋‚˜ ์•จ๋ฒ”์—์„œ ์‚ฌ์ง„์„ ๊ณ ๋ฅผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

UIImagePickerDelegate

๐Ÿ’ก A set of methods that your delegate object must implement to interact with the image picker interface.

๊ทธ๋ฆฌ๊ณ  UIImagePickerDelegate๋Š” Image Picker์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. UIImagePickerDelegate๋ฅผ ์ฑ„ํƒํ•˜๋ฉด ์ด๋ฏธ์ง€๋ฅผ ๊ณ ๋ฅด๋Š” ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋™์ž‘์„ ์ง€์›๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

UINavigationControllerDelegate

๐Ÿ’ก Use a navigation controller delegate (a custom object that implements this protocol) to modify behavior when a view controller is pushed or popped from the navigation stack of a UINavigationController object.

UINaviationControllerDelegate๋Š” ํ™”๋ฉด์ด ์ „ํ™˜๋  ๋•Œ์˜ ๋™์ž‘์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. Image Picker์—์„œ ์‚ฌ์ง„์„ ์„ ํƒํ•˜๊ฑฐ๋‚˜, ์ทจ์†Œํ–ˆ์„ ๋•Œ ๋‹ค์‹œ ์›๋ž˜ ์‚ฌ์šฉ์ค‘์ด๋˜ ๋ทฐ๋กœ ๋Œ์•„์˜ค๋Š” ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ์‚ฌ์ง„ ์•จ๋ฒ”์—์„œ ์ด๋ฏธ๋ฅผ ๊ณ ๋ฅด๊ณ  ๋‹ค์‹œ ์›๋ž˜ํ™”๋ฉด์œผ๋กœ ๋Œ์•„์˜ค๋Š” ์ด๋ฒคํŠธ๋“ค์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ UIImagePickerControllerDelegate ์™€ UINavigationControllerDelegate๋ฅผ ์ฑ„ํƒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { }

https://github.com/raywenderlich/swift-style-guide ์— ๋”ฐ๋ฅด๋ฉด, ํ”„๋กœํ† ์ฝœ์€ extension์œผ๋กœ ๋”ฐ๋กœ ๋นผ์„œ ์ฑ„ํƒํ•˜๋„๋ก ํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค!

3. ๊ถŒํ•œ ์„ค์ •ํ•˜๊ธฐ

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‚ฌ์šฉ์ž์˜ ์‚ฌ์ง„์ฒฉ์„ ์—ด์–ด์„œ ์•ˆ์—์žˆ๋Š” ์‚ฌ์ง„์„ ๊ฐ€์ ธ์˜จ๋‹ค๋Š” ๊ฒƒ์€ ๊ฝค๋‚˜ ์œ„ํ—˜ํ•œ ์ผ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์€ ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ—ˆ์šฉํ•ด๊ธฐ ์œ„ํ•ด์„œ ์•ฑ์— ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ํ”„๋กœ์ ํŠธ์˜ info.plist๋ฅผ ์—ด๊ณ ,

ํ•˜๋‚˜์˜ ์—”ํŠธ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค. "Privacy - Photo Library Usage Description" ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์‚ฌ์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

3. Image Picket ์—ด๊ธฐ

์ด์ œ ์‚ฌ์ง„์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ Image Picker๋ฅผ ๋ถˆ๋Ÿฌ์™€์•ผํ•ฉ๋‹ˆ๋‹ค. ImagePicker ์—ญ์‹œ๋„ ๋ณ„๋„์˜ ๋ทฐ ์ด๊ธฐ ๋•Œ๋ฌธ์— ImagePickerController์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ์— ํ˜„์žฌ ํ™”๋ฉด ์œ„์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { 
    @IBAction func openPhotosButtenPressed(_ sender: Any) { 
        let imagePicker = UIImagePickerController() 
        imagePicker.delegate = self 
        imagePicker.sourceType = .photoLibrary present(imagePicker, animated: true) 
    } 
}

์ด์ „์— ์ •์˜ํ•œ IBAction ์•ˆ์— UIImagePickerController ์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ํƒ€์ž…์„ ์‚ฌ์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹น์žฅ์€ ํ•„์š”ํ•˜์ง€ ์•Š์ง€๋งŒ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ Image Picker์˜ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•˜๊ธฐ ์œ„ํ•ด delegate์— ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ค๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ™”๋ฉด์— ํ‘œ์‹œํ•˜๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ด๋ฏธ์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” Image Picker๊ฐ€ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

4. ์„ ํƒ๋œ ์‚ฌ์ง„ ์ด์šฉํ•˜๊ธฐ

์œ„์—์„œ ์—ด๋ฆฐ Image Picker์—์„œ ์‚ฌ์ง„์„ ์„ ํƒํ•ด๋„ ์•„๋ฌด ๋ณ€ํ™”๋„ ์—†์Šต๋‹ˆ๋‹ค. ์•„์ง ์„ ํƒ๋œ ์‚ฌ์ง„์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š์•˜์œผ๋‹ˆ๊นŒ์š”! ์ด๋Ÿฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด UIImagePickerControllerDelegate์—์„œ ์ œ๊ณตํ•˜๋Š” imagePickerController ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 func imagePickerController(_ picker: UIImagePickerController, 
  didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { }
๐Ÿ’ก Tells the delegate that the user picked a still image or movie.

์ด ๋ฉ”์„œ๋“œ๋Š” ๋ธ๋ ˆ๊ฒŒ์ดํŠธ์—๊ฒŒ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์ง„์„ ๋‹ค ๊ณจ๋ผ๋ƒˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ์ธ์ž๋กœ ์ „๋‹ฌ๋˜๋Š” didFinishPickingMediaWithInfo ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ์‚ฌ์ง„์ด ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ Image Picker๋Š” ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—๊ฒŒ ์œ„์ž„๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์‚ฌ์ง„์„ ๊ณ ๋ฅธ ํ›„์˜ ์ด๋ฒคํŠธ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

didFinishPickingMediaWithInfo์˜ ๋‚ด๋ถ€์—๋Š” ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ๋กœ ๋‹ค์–‘ํ•œ ์ •๋ณด๋“ค์ด ๋“ค์–ด๊ฐ€์žˆ์Šต๋‹ˆ๋‹ค.

[__C.UIImagePickerControllerInfoKey(_rawValue: UIImagePickerControllerImageURL): file:///Users/jeonyeohun/Library/Developer/CoreSimulator/Devices/4980723E-92F5-4C7E-8F32-563E13A596BE/data/Containers/Data/Application/FC2D69DE-4D7E-41D2-B709-0AD4842D8F14/tmp/830C1E7B-FC23-41BB-A34A-293BACF85E8A.jpeg, 
__C.UIImagePickerControllerInfoKey(_rawValue: UIImagePickerControllerMediaType): public.image, 
__C.UIImagePickerControllerInfoKey(_rawValue: UIImagePickerControllerReferenceURL): assets-library://asset/asset.JPG?id=106E99A1-4F6A-45A2-B320-B0AD4A8E8473&ext=JPG, 
__C.UIImagePickerControllerInfoKey(_rawValue: UIImagePickerControllerOriginalImage): <UIImage:0x60000301ce10 anonymous {4288, 2848}>]

์ด ์ค‘์—์„œ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฑด UIImageView์— ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” UIImage ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ๋งˆ์ง€๋ง‰์— ์žˆ๋Š”
UIImagePickerControllerOriginalImage๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด ๋˜๊ฒ ๋„ค์š”! ๋ฌธ๋ฒ•์ด ์กฐ๊ธˆ ๋ฐ”๋€Œ์–ด์„œ ํ‚ค ๊ฐ’์€ "UIImagePickerController.InfoKey.originalImage" ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์ด ๊ฐ’์„ ์ด์šฉํ•ด์„œ ์ด๋ฏธ์ง€ ๋ทฐ๋ฅผ ์ฑ„์›Œ์ฃผ๋Š” ์ผ๋งŒ ๋‚จ์•˜๋„ค์š”.

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 
    if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { 
    	self.imageView.image = image 
    } 
    dismiss(animated: true, completion: nil)
}

์ด๋ ‡๊ฒŒ ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์„ ํ•ด์„œ ๋ž˜ํ•‘์„ ํ’€์–ด์ฃผ๊ณ  ์ด๋ฏธ์ง€ ๋ทฐ์˜ ๋ฐ์ดํ„ฐ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋์ž…๋‹ˆ๋‹ค! ๋งˆ์ง€๋ง‰์˜ dismiss๋Š” ์—ด๋ฆฐ Image Picker์˜ ํ™”๋ฉด์„ ๋‹ซ๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค!

5. ๊ฒฐ๊ณผ ํ™•์ธํ•˜๊ธฐ

์ •๋ฆฌ

1. ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์— UIImagePickerControllerDelegate, UINavigationControllerDelegate ๋ฅผ ์ฑ„ํƒํ•œ๋‹ค.
2. Privacy - Photo Library Usage Description ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
3. ImagePicketController ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ delegate๋กœ ์„ค์ •ํ•œ๋‹ค.
4. imagePickerController ๋ฉ”์„œ๋“œ์— ์„ ํƒ๋œ ์‚ฌ์ง„์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ •์˜ํ•œ๋‹ค.