[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

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

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

WPTouchでモバイルテーマ(iPhone用のテーマ)に戻すボタンが表示されない場合


使用しているPCのテーマによっては「WPTouch」のモバイルテーマ(iPhone用のテーマ)に戻すボタンが表示されない場合があります。

原因としては、使用しているテーマのスタイルシートが原因な事がほとんどですが、

ダウンロードして来て使用しているテーマだとスタイルシートに大改修はなるべく入れたくないと思うのが当然です。

その時の対処方法を以下に記述します。

原因1:「wp_footer」がfooter.phpで呼ばれていない

「WPTouch」のモバイルテーマへの切り替えボタンは

// モバイルテーマの追加
add_action( 'wp_footer', 'wptouch_switch' );

という風に、wp_footerへのアクションフックで実装されています。

なので「wp_footer」が存在しないと表示処理自体が実行されないので、「wp_footer」をcallするようにしましょう。

原因2:スタイルシートのx-indexや、positionの設定により思った位置に表示されない

HTML上は書き出されているが、他のタグの後ろに隠れていたり、思った箇所と異なる箇所に表示される場合の対処です。

モバイルテーマの表示用の関数は「wptouch_switch」と言う名前で実装されています。

なので、直接表示したい箇所で呼び出しましょう、また

アクションフックに登録されているので、アクションフックが動作する前に対象のアクションフックを削除も行うようにします。

表示したい場所で以下の記述を追加します。

<?php 
if (function_exists('wptouch_switch')) {
	wptouch_switch();
	remove_action( 'wp_footer', 'wptouch_switch' );
}
?>

「remove_action」の呼び出しは、「wp_footer」を呼び出す前に実行される箇所に記述するようにしてください。

(今回は、記述箇所が「wp_footer」前だったので同じタイミング実行しています。

これで、以下のようになり

モバイルテーマに戻す為のボタンが表示されるようになります。

 

参考にしたサイト

  1. WPtouchでiPhone用テーマに戻すには?
  2. WPtouchでiPhone用テーマへの表示ができない(使えない)場合の対処方法

iPhoneアプリのUIButtonでチェックボックスを実装する方法


 

iPhoneアプリのデフォルトのUIではAndroidやHTMLで実現出来るチェックボックスのようなものがありません。

ですので、UIButtonを使用してチェックボックスを作って実現してみました。

用意するもの

  1. チェックボックス用の画像
  2. UIButtonを継承したサブクラスの実装

この2つで実装できます。

まず、画像はAndroidで表示されるチェックボックスの画像を切りだして作成しました。

  

この3つの画像を使用します。

1.UIButtonのサブクラスを作成する

  1. メニューの「File」 →「New」→「File」をクリックして「Choose a template for your new file」を表示します。

  2. 「Next」ボタンを押下して、Class名に「CheckboxButton」Subclass of に「UIButton」を入力して「Next」ボタンを押下する
  3. 「CheckboxButton.h」を編集
    #import <UIKit/UIKit.h>
    
    @interface CheckboxButton : UIButton
    
    @property (nonatomic, assign) BOOL checkBoxSelected;
    
    @end
  4. 「CheckboxButton.m」を編集する
    #import "CheckboxButton.h"
    
    @implementation CheckboxButton
    
    @synthesize checkBoxSelected = _checkBoxSelected;
    
    - (void)awakeFromNib
    {
        [super awakeFromNib];
        UIImage* nocheck = [UIImage imageNamed:@"nocheck.png"];
        UIImage* checked = [UIImage imageNamed:@"check.png"];
        UIImage* disable = [UIImage imageNamed:@"disable_check.png"];
        [self setBackgroundImage:nocheck forState:UIControlStateNormal];
        [self setBackgroundImage:checked forState:UIControlStateSelected];
        [self setBackgroundImage:checked forState:UIControlStateHighlighted];
        [self setBackgroundImage:disable forState:UIControlStateDisabled];
        [self addTarget:self action:@selector(checkboxPush:) forControlEvents:UIControlEventTouchUpInside];
        [self setState:self];
    }
    
    - (id)initWithFrame:(CGRect)frame
    {
        NSLog(@"initWithFrame");
        self = [super initWithFrame:frame];
        if (self) {
            // Initialization code
            UIImage* nocheck = [UIImage imageNamed:@"nocheck.png"];
            UIImage* checked = [UIImage imageNamed:@"check.png"];
            UIImage* disable = [UIImage imageNamed:@"disable_check.png"];
            [self setBackgroundImage:nocheck forState:UIControlStateNormal];
            [self setBackgroundImage:checked forState:UIControlStateSelected];
            [self setBackgroundImage:checked forState:UIControlStateHighlighted];
            [self setBackgroundImage:disable forState:UIControlStateDisabled];
            [self addTarget:self action:@selector(checkboxPush:) forControlEvents:UIControlEventTouchUpInside];
            [self setState:self];
        }
        return self;
    }
    
    - (void)checkboxPush:(CheckboxButton*) button {
        button.checkBoxSelected = !button.checkBoxSelected;
        [button setState:button];
    }
    
    - (void)setState:(CheckboxButton*) button
    {
        if (button.checkBoxSelected) {
            [button setSelected:YES];
        } else {
            [button setSelected:NO];
        }
    }
    
    @end

これで、「CheckboxButton」クラスの作成は終了です。

次は、作成した「CheckboxButton」を使用する方法です。

2.「CheckboxButton」の使用方法

  1. Storyboardまたは、nibファイルに「Round Rect Button」を設置する。
  2. 設置したButtonのClass名に「CheckboxButton」を設定する

これだけでチェックボックスが実装できます。

実際に動かしたイメージが以下になります。

チェックボックスOFF時の状態

チェックボックスON時の状態

こんな感じでチェックボックスが実装できます。

「checkBoxSelected」の状態を取得することでチェックがON/OFFなのか判断できます。

return top