FMDBで簡単写真アルバムを作ろう Part.6 ~【iPhone】UITextField,UIActionSheet,UIImagePickerControllerとメモ、写真の保存~

前回:FMDBで簡単写真アルバムを作ろう Part.5 ~【iPhone】SQLiteのデータを出し入れするためのクラスをつくる~

簡単写真アルバムのソースコードGitHubからどうぞ
ー>https://github.com/ics-hiro/SelfPhotoLibrary


前々回NewViewControllerの画面を作りました。
続きをやっていきます。

NavigationBarにSaveボタンを設置する

NewViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 右上の「Save」ボタン。押したら、save_memo_photoメソッドが実行される
    UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save_memo_photo)];
    self.navigationItem.rightBarButtonItem = button;
}

UITextFieldのデリゲートメソッドで、Returnキーが押されたときにキーボードをしまう

UITextFieldのデリゲートメソッドを使うので、NewViewController.hにデリゲートを宣言します。

NewViewController.h

#import <UIKit/UIKit.h>

@interface NewViewController : UIViewController <UITextFieldDelegate> //<-宣言

- (IBAction)selectPhoto:(id)sender;
@property (weak, nonatomic) IBOutlet UIButton *btn_select;
@property (weak, nonatomic) IBOutlet UITextField *memoField;
@property (weak, nonatomic) IBOutlet UIImageView *image_view;
@end

あとは、自クラスでデリゲートメソッドを処理するので、memoFieldのデリゲートにselfを指定します。

NewViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save_memo_photo)];
    self.navigationItem.rightBarButtonItem = button;
    
    memoField.delegate = self; //<-追加
}

最後に、キーボードでReturnキーが押されたときに呼ばれる処理を実装します。

-(BOOL)textFieldShouldReturn:(UITextField*)textField{
    [memoField resignFirstResponder];
    return YES;
}

UIActionSheetを表示させる

UIActionSheetもUITextFieldのときと同様に、デリゲートを宣言する必要があります。

複数のデリゲートを宣言する場合、カンマで並列に記述できます。

NewViewController.h

#import <UIKit/UIKit.h>

@interface NewViewController : UIViewController <UIActionSheetDelegate,UITextFieldDelegate> //<-UIActionSheetDelegateを追加

- (IBAction)selectPhoto:(id)sender;
@property (weak, nonatomic) IBOutlet UIButton *btn_select;
@property (weak, nonatomic) IBOutlet UITextField *memoField;
@property (weak, nonatomic) IBOutlet UIImageView *image_view;
@end

「Select Photo」という名前の入ったボタンを設置しましたよね。
これはIBActionで接続していて、メソッドの名前は「- (IBAction)selectPhoto:(id)sender」です。

このボタンを押したときにアクションシートが表示され、カメラを選ぶかフォトライブラリを選ぶかを選択できるようにします。

NewViewController.m

- (IBAction)selectPhoto:(id)sender {
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Camera",@"Photo Library",nil];
    [actionSheet showInView:self.view];
}

デリゲートにselfを指定しています。

UIImagePickerControllerをModalで表示させる

そして、アクションシートのそれぞれのボタンがタップされたときにどういう処理をするのか、を書きましょう。

NewViewController.m

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    UIImagePickerControllerSourceType sourceType;
    switch (buttonIndex) {
        case 0: //一番上のボタン
            sourceType = UIImagePickerControllerSourceTypeCamera;
            break;
        case 1: //二番目のボタン
            sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            break;
            
        default:
            return;
    }
    
    if (![UIImagePickerController isSourceTypeAvailable:sourceType]) {
        return;
    }
    

    /*---イメージピッカーの生成---*/
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    // イメージピッカーのタイプを代入
    picker.sourceType = sourceType;
    // 写真を編集する
    picker.allowsEditing = YES;

    picker.delegate = self;
    
    [self presentModalViewController:picker animated:YES]; //モーダル表示
    
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex」というメソッドは、
アクションシートのボタンがタップされたときに呼ばれます。

UIImagePickerControllerSourceTypeは「Camera」がタップされるか「Photo Library」がタップされるかで、代入されるタイプが異なることになります。

UIImagePickerControllerで取得した写真をリサイズする

カメラ、あるいはフォトライブラリから画像を取得してくると思いますが、
その画像をいじるのが「- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info」です。

NewViewController.m

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissModalViewControllerAnimated:YES]; //イメージピッカーを閉じる
    
    // オリジナル画像を取得する
    UIImage*    originalImage;
    originalImage = [info objectForKey:UIImagePickerControllerEditedImage];
    
    
    // グラフィックスコンテキストを作る
    CGSize  size = { 320, 400 };
    UIGraphicsBeginImageContext(size);
    
    // 画像を縮小して描画する
    CGRect  rect;
    rect.origin = CGPointZero;
    rect.size = size;
    [originalImage drawInRect:rect];
    
    // 描画した画像を取得する
    UIImage*    shrinkedImage;
    shrinkedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    image_view.image = shrinkedImage;
    
}

originalImageに、イメージピッカーで編集後の画像を代入しています(UIImagePickerControllerEditedImage

UIGraphicsですね。

しっかりドキュメントを読みましょう。
右側のQuick Helpのところからクリックしてドキュメントを開いて、ちょいちょい確認しながら開発していくことをお勧めします。

データベースに保存するため、UIImageからNSDataへ変換する

取得してきた画像を処理するのが「- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info」だというのは上記の通りです。

ここで、この画像(UIImage)をNSDataに変換して、データベースにいれることのできるデータ型にしましょう。

最後のsave_memo_photoメソッドでこのNSDataを使うので、NewViewControllerクラスのインスタンス変数として扱います。


NewViewController.m

@implementation NewViewController
{
    //↓追加
    @private
    NSData *imageData;
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissModalViewControllerAnimated:YES];
    // オリジナル画像を取得する
    UIImage*    originalImage;
    originalImage = [info objectForKey:UIImagePickerControllerEditedImage];
    
    
    // グラフィックスコンテキストを作る
    CGSize  size = { 320, 400 };
    UIGraphicsBeginImageContext(size);
    
    // 画像を縮小して描画する
    CGRect  rect;
    rect.origin = CGPointZero;
    rect.size = size;
    [originalImage drawInRect:rect];
    
    // 描画した画像を取得する
    UIImage*    shrinkedImage;
    shrinkedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    image_view.image = shrinkedImage;
    
    // データベースに入れるためにUIImageをNSDataに変換、保存のときに使う(save_memo_photoメソッド)
    // UIImageJPEGRepresentation関数を使い、UIImageが保持する画像データをJPEG形式で抽出できる
    imageData = [[NSData alloc] initWithData:UIImageJPEGRepresentation(shrinkedImage, 0.8)]; //<-追加
    
}

今回はUIImageJPEGRepresentation関数を使いましたが、UIImagePNGRepresentation関数を使うことも出来ます。

クオリティを0.0から1.0まで設定でき、今回は0.8としている。
Quick Helpを引用すると、
「compressionQuality: The quality of the resulting JPEG image, expressed as a value from 0.0 to 1.0.」


DataModelsクラスを使って、データベースにデータを挿入する

では、上記のimageDataと、memoFieldの文字列をデータベースに保存しましょう。

NewViewControlle.m

- (void)save_memo_photo
{
    // メモ、写真を選択してないと進めない
    if ([memoField.text length] > 0 && [imageData length] != 0) {
        
        [DataModels insertTitle:memoField.text Contents:imageData]; //DataModelsクラスのクラスメソッド
        
        [self.navigationController popToRootViewControllerAnimated:YES];  //NavigationControllerのホームに戻る
        
    }else { // メモが書かれていない、あるいは写真が選択されていないとアラート
        UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"写真とメモ" message:@"写真を選んでメモを書いてね" delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
        [av show];
    }
    
}

コードのスクリーンショットを撮って視覚的に表現すると、

memoField.textの文字数を数えるのはlengthを使えば良い。文字カウントはマイナスになることはないので正という条件で次に進める。NSDataの場合は中身が入っていないと偽となり、偽は0なので、0でない場合に次に進めるようにした。

保存がうまくできたら、NavigationControllerのホームに戻っている。
それが「[self.navigationController popToRootViewControllerAnimated:YES];」という部分。
つまり、ViewControllerに帰るということ。


もしメモか写真が不十分な場合はアラートを出し、メモを書くことと写真を選択してくださいと表示する。



簡単写真アルバムアプリ記事一覧
FMDBで簡単写真アルバムを作ろう Part.1 ~メモが書ける写真アルバムをつくる~
FMDBで簡単写真アルバムを作ろう Part.2 ~Xcode4.3,SingleViewApplication,FMDB準備~
FMDBで簡単写真アルバムを作ろう Part.3 ~必要なファイルを追加して整理しよう~
FMDBで簡単写真アルバムを作ろう Part.4 ~NavigationBarと画面遷移~
FMDBで簡単写真アルバムを作ろう Part.5 ~【iPhone】SQLiteのデータを出し入れするためのクラスをつくる~
FMDBで簡単写真アルバムを作ろう Part.6 ~【iPhone】UITextField,UIActionSheet,UIImagePickerControllerとメモ、写真の保存~
FMDBで簡単写真アルバムを作ろう Part.7 ~【iPhone】SQLiteのデータを取り出してTableViewに表示~
FMDBで簡単写真アルバムを作ろう Part.8 ~【iPhone】TableViewの画面遷移、異なるView間での値の受け渡し~
FMDBで簡単写真アルバムを作ろう Part.9 ~【iPhone】TableViewのセルを削除、commitEditingStyle ~
FMDBで簡単写真アルバムを作ろう 最終章 ~簡単写真アルバムの完成~

======================
当ブログ管理人のツイッターこちら
◎フォローしてくださると泣いて喜びます!ツイッター上で当ブログの質問などにもできるだけお答えしますし、役に立つiPhoneアプリ開発情報もつぶやきます。個人的なご依頼(たとえば、プログラミングの家庭教師、Skypeレッスンをしてくれないか、iPhoneアプリ開発の勉強会ってやってるの、とかですね)でもかまいません。
スカイプレッスンについて
開発をしているとその都度ぶつかる問題があると思いますが、検索で調べてもなかなかわからない、あるいは調べても非常に時間がかかる場合があると思います。開発者のみなさんもお忙しいと思いますので、私のレッスンを受けながら開発を進めていただけると、大幅にお時間を短縮できます。加えて、iPhoneアプリ開発の基礎、応用が身につき、今後の開発もスムーズに進められます

お問い合わせはツイッター、またはhiyoshimarukoアットマークgmail.comまでお願いします。(アットマークを@にしてください)お待ちしております!