カテゴリー ‘ iPhone

iPhoneアプリのUITableViewの編集モードを使う場合の注意点


 

iPhoneアプリでTableViewを使用している場合、「編集モード」を使うとかなり便利にデータ削除が行える

UITableViewControllerを継承しているのならあまり問題ないかと思うのですが、

UIViewControllerで「UITableViewDelegate, UITableViewDataSource」を独自に実装してUITableViewを操作する場合注意が必要になります。

注意が必要と言っても1つだけ忘れないで置くことを覚えておくだけです。

「- (void)setEditing:(BOOL)editing animated:(BOOL)animated」

このメソッドの実装を忘れない事です。このメソッドを書かないで置くとEditボタンを押下しても、うんともすんともいいません。

さみしい状態になるので注意しましょう。

iOSアプリケーションの共通に使用されるディレクトリ


 

iOSアプリケーションを開発するときに使用するディレクトリ構成の備忘録

ディレクトリ 概要
<Application_Home>/AppName .app
アプリケーションを含むバンドルディレクトリ。
このディレクトリ内にプログラムから書き換えを行うとアプリが起動できなくなります。
iTunesでバックアップされない
<Application_Home>/Documents/
アプリケーション内でデータファイルを書きだすディレクトリ。
iTunesでバックアップされる
<Application_Home>/Documents/Inbox
外部エンティティからアプリケーションに対して要求されたファイルのアクセスに使用する。
iTunesでバックアップされる

<Application_Home>/Library/

アプリケーションのデータファイル以外のファイル用の最上位ディレクトリ。
iTunesでバックアップされる
<Application_Home>/tmp/
アプリケーションを次に起動するまで保持する必要のない一時ファイルを書き込むディレクトリ。
iTunesでバックアップされる

これを押さえておかないとファイルをリソースフォルダ内に出力してしまったりするので注意しましょう

[iPhoneアプリ]TabBarControllerでタブに設定されているViewContllerを入れ替える


 

iPhoneアプリで「TabBarController」で実装していると、特定のタブの表示をごっそり入れ替えたい場合がある。

この時、タブに設定されているViewContller毎、入れ替えてしまう方法

    NSMutableArray *tabs = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
    SubTabViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"SubTabViewController"];
    UIViewController *tmpController = [tabs objectAtIndex:1];
    controller.tabBarItem = tmpController.tabBarItem;
    [tabs replaceObjectAtIndex:1 withObject:controller];
    [self.tabBarController setViewControllers:tabs animated:NO];
  • 2行目で入れ替えたいViewContllerのインスタンスを生成
  • 3-4行目で、tabBarItemを設定
  • 5行目でタブの入れ替え(今回は2つめのタブを入れ替えたのでIndexは「1」を指定)

これで、見事ViewControllerが入れ替わって下に表示されているタブは、そのまま使用されます。

[iPhoneアプリ]TabBarControllerで選択中のTabをプログラムで切り替える方法


 

iPhoneアプリの「TabBarController」でプログラムで選択中のタブを切り替える方法

// Indexは0から始まる
self.tabBarController.selectedIndex = 0;

これで、選択中のタブを切り替える事が出来る、単純!

iPhoneで日付を入力するモーダルウインドウの作り方


 

iPhoneでの日付の入力方法は、ドラムロールのようなこちら

「UIDatePicker」で行うのが普通だと思います。

これが入力ように画面を覆うように表示されていたらすごく邪魔ですよね?

なので、こいつを文字列入力のキーボードのように下からニョキっと出るように改造してみたいと思います。

動作イメージ

1.nibファイルの作成

まず完成図はこちら、

UIを設置する

  1. Viewを配置「幅:320 × 高さ:480」で設置する
  2. UIDatePickerを最下部に設置する
  3. UIToolBarをUIDatePickerの上に設置する
  4. UIBarButtonItemを2つUIToolBarに設置する
  5. ボタンの間に「Flexible Space Bar Button Item」を設置する

UIの設定を変更する

  1. File’s Ownerの設定
    1. 「Custom Class」に「ModalDatePicker」と入力する(この後に作るViewControllerの名前を設定)
  2. Viewの設定
    1. 「Background」をDefaultの色なしに設定する
    2. 「Width」を320 「Height」を480で設定する
    3. 「File’s Owner」とReferencing Outletsで接続する
  3. DatePickerの設定
    1. 「File’s Owner」とReferencing Outletsで接続する(この後に作成するViewControllerのhファイルに設定が必要)
  4. 左ボタンの設定
    1. 「File’s Owner」とSent Actionsで接続する(この後に作成するViewControllerのhファイルに設定が必要)
  5. 右ボタンの設定
    1. 「File’s Owner」とSent Actionsで接続する(この後に作成するViewControllerのhファイルに設定が必要)

2.ViewControllerの作成

  1. 「ModalViewContoller.h」の編集
    #import <UIKit/UIKit.h>
    
    @class ModalDatePicker;
    
    @protocol ModalDatePickerDelegate
    
    - (void) didDatePickerOKClicked:(ModalDatePicker *) controller selectedDate:(NSDate *) selectedDate pickerName:(NSString *) pickerName pickerTag:(NSInteger) pickerTag;
    - (void) didDatePickerCancelClicked:(ModalDatePicker *) controller pickerName:(NSString *) pickerName pickerTag:(NSInteger) pickerTag;
    
    @end
    
    @interface ModalDatePicker : UIViewController
    
    @property (weak, nonatomic) IBOutlet UIDatePicker *picker;
    @property (nonatomic, assign) id<ModalDatePickerDelegate> delegate;
    @property (nonatomic, retain) NSString *pickerName;
    @property (nonatomic, assign) NSInteger pickerTag;
    @property (nonatomic, retain) NSDate *dispDate;
    
    - (IBAction)okClicked:(id)sender;
    - (IBAction)cancelClicked:(id)sender;
    
    @end
  2. 「ModalViewController.m」の編集
    #import "ModalDatePicker.h"
    
    @interface ModalDatePicker ()
    
    @end
    
    @implementation ModalDatePicker
    @synthesize picker = _picker, delegate = _delegate, pickerName = _pickerName, dispDate = _dispDate, pickerTag = _pickerTag;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view.
    }
    
    - (void)viewDidAppear:(BOOL)animated {
        if (self.dispDate != nil) {
            [self.picker setDate:self.dispDate];
        }
    }
    
    - (void)viewDidUnload
    {
        [self setPicker: nil];
        [super viewDidUnload];
        // Release any retained subviews of the main view.
    }
    
    - (IBAction)okClicked:(id)sender {
        [self.delegate didDatePickerOKClicked:self selectedDate:self.picker.date pickerName:self.pickerName pickerTag:self.pickerTag];
    }
    
    - (IBAction)cancelClicked:(id)sender {
        [self.delegate didDatePickerCancelClicked:self pickerName:self.pickerName pickerTag:self.pickerTag];
    }
    
    @end

これで「ModalDatePicker」は作成完了です。

使用方法

  1. ボタンを押下したら、「ModalDatePicker」を表示する
    - (IBAction)showBtnClicked:(id)sender
    {
    	// self.pickarは、ModalDatePicker型のインスタンス変数です。
    	self.picker = [[ModalDatePicker alloc] init];
    	self.datePicker.pickerName = @"どこから呼ばれたか特定する為に設定";
    	self.datePicker.dispDate = (self.dispDate != nil) ? self.dispDate : [NSDate date];
    	self.datePicker.delegate = self;
    	[self showModel:self.datePicker.view];
    }
    
    - (void) showModel:(UIView *) modalView
    {
    	UIWindow *mainWindow = (((AppDelegate *) [UIApplication sharedApplication].delegate).window);
    	CGPoint middleCenter = modalView.center;
    	CGSize offSize = [UIScreen mainScreen].bounds.size;
    	CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
    	modalView.center = offScreenCenter;
    	[mainWindow addSubview:modalView];
    	[UIView beginAnimations:nil context:nil];
    	[UIView setAnimationDuration:0.5];
    	modalView.center = middleCenter;
    	[UIView commitAnimations];
    }
  2. 「ModalDataPicker」のdelegateを実装する
    - (void) didDatePickerOKClicked:(ModalDatePicker *)controller selectedDate:(NSDate *)selectedDate pickerName:(NSString *)pickerName pickerTag:(NSInteger) pickerTag
    {
    	[self hideModal:controller.view];
    	controller.delegate = nil;
    	NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    	[formatter setDateFormat:@"yyyy年MM月dd日"];
    	if ([pickerName isEqualToString:@"どこから呼ばれたか特定する為に設定") {
    		self.date = selectedDate;
    		self.label.text = [formatter stringFromDate:self.date];
    	}
    }
    
    - (void) didDatePickerCancelClicked:(ModalDatePicker *)controller pickerName:(NSString *)pickerName pickerTag:(NSInteger) pickerTag
    {
    	[self hideModal:controller.view];
    	controller.delegate = nil;
    }
    
    - (void) hideModal:(UIView*) modalView
    {
    	CGSize offSize = [UIScreen mainScreen].bounds.size;
    	CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
    	[UIView beginAnimations:nil context:(__bridge_retained void *)modalView];
    	[UIView setAnimationDuration:0.3];
    	[UIView setAnimationDelegate:self];
    	[UIView setAnimationDidStopSelector:@selector(hideModalEnded:finished:context:)];
    	modalView.center = offScreenCenter;
    	[UIView commitAnimations];
    }
    
    - (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    {
        UIView *modalView = (__bridge_transfer UIView *)context;
        [modalView removeFromSuperview];
    }

これで「ModalDatePicker」の呼び出しと、delegateの実装ができました。

1つのViewContllerで複数の「ModalDatePicker」を呼び出す必要がある場合は、

  • pickerName
  • pickerTag

を使用してどのボタンから呼び出されたかを判断することができます。

これを、応用することで様々な入力方法をモーダルウインドウ化出来るようになります。

return top