写真をピンチ操作で拡大縮小する

# はじめに

フォトライブラリから選択した写真をViewに反映してピンチ操作で拡大縮小するコードを書いていきます。

# フォトライブラリから写真を選択する

UIImageViewを配置してmainImageViewとします。このmainImageViewに写真を表示します。

フォトライブラリから写真を選択するために`UIImagePickerController`を利用します。
今回は写真の取得先にフォトライブラリ（PhotoLibrary）を指定します。
ほかにはカメラ（Camera）、フォトアルバム（SavedPhotosAlbum）が指定できます。

```swift:sample1.swift
import Foundation

class ImagePickerViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
	
	@IBOutlet weak var mainImageView: UIImageView!
	
	override func viewDidLoad() {
		super.viewDidLoad()
		// Do any additional setup after loading the view, typically from a nib.
		
		let picker = UIImagePickerController()
		picker.delegate = self
		picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
		self.presentViewController(picker, animated: true, completion: nil)
	}
	
	override func didReceiveMemoryWarning() {
		super.didReceiveMemoryWarning()
		// Dispose of any resources that can be recreated.
	}
	
	func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
		let image = info[UIImagePickerControllerOriginalImage] as UIImage
		self.mainImageView.image = image
		picker.dismissViewControllerAnimated(true, completion: nil)
	}
	
	func imagePickerControllerDidCancel(picker: UIImagePickerController) {
		picker.dismissViewControllerAnimated(true, completion: nil)
	}
}
```

実行すると、写真へのアクセス許可が求められます。「OK」をタップすると写真選択画面に遷移します。
写真を選択するとmainImageViewに写真が反映されます。

![スライド](https://qiita-image-store.s3.amazonaws.com/0/3862/c3aad124-0db2-dada-f629-1408943b69e8.jpeg)

# 拡大縮小できるようにする

mainImageViewに写真を配置することができました。
次にピンチ操作で写真を拡大縮小するためにコードを書き換えます。

UIScrollViewを配置してmainScrollViewとします。このmainScrollViewの中にmainImageViewを配置します。

![スライド](https://qiita-image-store.s3.amazonaws.com/0/3862/1f30bd32-408b-595f-bd20-b39f974b5a5b.jpeg)

mainScrollViewの最大、最小のスケールをそれぞれ設定します。
`func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?`でmainImageViewを返すようにします。

```swift:sample2.swift
import Foundation

class ImagePickerViewController: GAViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIScrollViewDelegate {
	
	@IBOutlet weak var mainScrollView: UIScrollView!
	@IBOutlet weak var mainImageView: UIImageView!
	
	override func viewDidLoad() {
		super.viewDidLoad()
		// Do any additional setup after loading the view, typically from a nib.
		
		self.mainScrollView.maximumZoomScale = 3.0
		self.mainScrollView.minimumZoomScale = 0.1
		self.mainScrollView.delegate = self
		
		let picker = UIImagePickerController()
		picker.delegate = self
		picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
		self.presentViewController(picker, animated: true, completion: nil)
	}
		
	override func didReceiveMemoryWarning() {
		super.didReceiveMemoryWarning()
		// Dispose of any resources that can be recreated.
	}
	
	func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
		let image = info[UIImagePickerControllerOriginalImage] as UIImage
		self.mainImageView.image = image
		picker.dismissViewControllerAnimated(true, completion: nil)
	}
	
	func imagePickerControllerDidCancel(picker: UIImagePickerController) {
		picker.dismissViewControllerAnimated(true, completion: toRootView)
	}
	
	func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
		return self.mainImageView
	}
}
```

実行します。
これでピンチ操作による写真の拡大縮小ができるようになりました。

![スライド](https://qiita-image-store.s3.amazonaws.com/0/3862/1614530b-44fb-1360-a695-42c05d921b15.jpeg)


# おまけ

UIScrollViewを利用すると、タッチイベントが取得できなくなります。
具体的には、以下のように記述しても呼ばれることはありません。

```swift:sample3.swift
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {

}
```

これを解決するには、UIScrollViewのサブクラスとして実装するか、カテゴリを利用します。
今回はカテゴリを利用して記述します。
タッチイベントを取得してnextResponderのタッチイベントを呼びます。

```swift:sample4.swift
extension UIScrollView {
	public override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
		self.nextResponder()?.touchesBegan(touches, withEvent: event)
	}
}
```