Swiftでカメラロールから写真データを保存する話
おはようございます。あおかび (ん)です。
この間やっとアプリケーション作りがひと段落したので、
その間に学んだことをずらずらっと書いていこうと思っております。
今回はSwiftを使ってカメラロールから写真データを引っ張ってくる方法を書いていきたいと思います。
ボタンを一つ置いて、そのボタンがクリックされたらカメラロールにアクセス、
その画像をローカルデータとして保存しておくところまでやっておきたいと思います。
DBの部分は今回は割愛します。
1.ボタンを配置して、カメラロールにアクセス
ViewController.swiftにまず、AssetsLibraryをimportした後、
UIViewControllerに加えてUIImagePickerControllerDelegateとUINavigationControllerDelegateを継承(?)しましょう。
/* ViewController.swift */ import UIKit import AssetsLibrary class testViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
つづいてviewDidLoadメソッドにてボタンを配置、アクションは今回はaccessCamerarollとしました。
override func viewDidLoad() { self.view.backgroundColor = UIColor.whiteColor() super.viewDidLoad() let button: UIButton = UIButton() button.frame = CGRectMake(100, 100, 100, 100) button.setTitle("Access!", forState: UIControlState.Normal) button.backgroundColor = UIColor.blueColor() button.addTarget(self, action: Selector("accessCameraroll:"), forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) }
そのaccessCamerarollメソッドは次のようになっています。
// カメラロールから写真を選ぶためのメソッド func accessCameraroll(button: UIButton) { if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) { let controller = UIImagePickerController() controller.delegate = self controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary self.presentViewController(controller, animated: true, completion: nil) } }
ここまででとりあえずカメラロールにアクセスすることはできました!
次はカメラロールから選択した写真を保存しましょう。
2.選択した写真をローカルストレージに保存
写真を選択した時に呼ばれるメソッドに
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { }
というメソッドがあります。この関数内で、選択した画像を保存していきましょう。
// 写真を選択した時に呼ばれるメソッド func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { if info[UIImagePickerControllerOriginalImage] != nil { let image: UIImage? = info[UIImagePickerControllerOriginalImage] as! UIImage? let pictURL: NSURL = info[UIImagePickerControllerReferenceURL] as! NSURL var library: ALAssetsLibrary = ALAssetsLibrary() var data: NSData? let sema: dispatch_semaphore_t = dispatch_semaphore_create(0) let queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) var getImage: UIImage? dispatch_async(queue, {() -> Void in library.assetForURL(pictURL, resultBlock: {(asset: ALAsset!) -> Void in let representation: ALAssetRepresentation? = asset.defaultRepresentation() getImage = UIImage(CGImage: representation!.fullResolutionImage().takeUnretainedValue())! data = UIImagePNGRepresentation(getImage!) dispatch_semaphore_signal(sema) }, failureBlock: {(error: NSError!) -> Void in println(error) dispatch_semaphore_signal(sema); }) }) dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); saveImage(data!) } picker.dismissViewControllerAnimated(true, completion: nil) let mainViewController: MainViewController = MainViewController() self.navigationController?.pushViewController(mainViewController, animated: true) } // 画像をローカルストレージに保存するメソッド func saveImage(data: NSData) { let dataPath = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as! Array<String>).first!.stringByAppendingPathComponent("test.jpg") var fileManager: NSFileManager = NSFileManager() data.writeToFile(dataPath, atomically: true) }
これで画像が保存されたはずです。
最初はAVFoundationとか使ってカメラにアクセスしたりしてたんですが、なんかうまくいかなかったですね...
コーディング能力、プログラミング能力の両方がこのままではやばい気がするよなー
勉強頑張っていきます。ありがとうございました、かびでした。。。
P.S.
コードの全容
import UIKit import AssetsLibrary class testViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { override func viewDidLoad() { self.view.backgroundColor = UIColor.whiteColor() super.viewDidLoad() let button: UIButton = UIButton() button.frame = CGRectMake(100, 100, 100, 100) button.setTitle("Access!", forState: UIControlState.Normal) button.backgroundColor = UIColor.blueColor() button.addTarget(self, action: Selector("accessCameraroll:"), forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) } // カメラロールから写真を選ぶためのメソッド func accessCameraroll(button: UIButton) { if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) { let controller = UIImagePickerController() controller.delegate = self controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary self.presentViewController(controller, animated: true, completion: nil) } } // 写真を選択した時に呼ばれるメソッド func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) { if info[UIImagePickerControllerOriginalImage] != nil { let image: UIImage? = info[UIImagePickerControllerOriginalImage] as! UIImage? let pictURL: NSURL = info[UIImagePickerControllerReferenceURL] as! NSURL var library: ALAssetsLibrary = ALAssetsLibrary() var data: NSData? let sema: dispatch_semaphore_t = dispatch_semaphore_create(0) let queue: dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) var getImage: UIImage? dispatch_async(queue, {() -> Void in library.assetForURL(pictURL, resultBlock: {(asset: ALAsset!) -> Void in let representation: ALAssetRepresentation? = asset.defaultRepresentation() getImage = UIImage(CGImage: representation!.fullResolutionImage().takeUnretainedValue())! data = UIImagePNGRepresentation(getImage!) dispatch_semaphore_signal(sema) }, failureBlock: {(error: NSError!) -> Void in println(error) dispatch_semaphore_signal(sema); }) }) dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); saveImage(data!) } picker.dismissViewControllerAnimated(true, completion: nil) let mainViewController: MainViewController = MainViewController() self.navigationController?.pushViewController(mainViewController, animated: true) } // 画像をローカルストレージに保存するメソッド func saveImage(data: NSData) { let dataPath = (NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as! Array<String>).first!.stringByAppendingPathComponent("test.jpg") var fileManager: NSFileManager = NSFileManager() data.writeToFile(dataPath, atomically: true) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }