Browsing all articles in 逆引き備忘録
7月
13

TapkuLibraryをXCode4に組み込む

Author msota    Category 逆引き備忘録     Tags

CoverFlowやカレンダーが使えるライブラリTapkuLibraryをXCode4で組み込んだ。

まず、ライブラリをgithubから取得する。

  • どこか適当にライブラリの置き場を決める(とりあえず~/Documents/dev/tapku にした)
  • ターミナルを開き、cdで置き場に移動
  • git clone git://github.com/devinross/tapkulibrary.git
  • ~/Documents/dev/tapku/tapkuLibrary ができる

続いて、プロジェクトに導入する。

  • XCodeで、TapkuLibraryを導入するプロジェクトを開く
  • 左側のツリーからFrameworksを選び、マウス右ボタンメニュー「Add files to project」を実行
  • 画面から ~/Documents/dev/tapku/tapkuLibrary/src/TapkuLibrary.xcodeproj を追加
  • 同様に ~/Documents/dev/tapku/tapkuLibrary/src/TapkuLibrary.bundle を追加

続いてBuild Phasesの設定をする。

  • PROJECTのTARGETSを選び、Build PhasesタブからTarget Dependenciesを選ぶ
  • +ボタンから、TapkuLibraryを追加する
  • 同じタブにある Link Binary With Libraries を選ぶ
  • +ボタンから、libTapkuLibrary.aを追加する
  • 同様に、MapKit、QuartzCoreを追加する

最後にBuild Settingsに追加する。

  • Build Settingsタブを選択する
  • タブの下にあるツールバーからAllを選択する
  • Header Search Pathsに、~/Documents/dev/tapku/tapkuLibrary/src/ を追加する
  • Other Linker Flagsに、-all_load -ObjC を追加する

アプリケーションへの組み込みは、当然ながらXCode3の時と同じ。

7月
12

カスタムキーボードを作成する

Author msota    Category 逆引き備忘録     Tags

iPhoneで文字入力する際のキーボードを、カスタムキーボードに変更した。目的としては、定型文しか入力しないフィールドに対して選択肢を用意し、入力を簡単にすることである。

それだけを目的とするならピッカーでも同じことはできるのだが、現在作っているアプリケーションでは、ピッカーをグルグル回して選択するよりも並んでいるボタン状のものから選ぶ方が好ましいと思われたので、カスタムキーボードにした。

さらに言うと、単に選ぶだけならUIAccessoryViewを使っても同じようなことが出来そうだが、本来のキーボードも併用して切り替えられるようにしたかったので、カスタムキーボードにしてみた次第である。

大雑把な手順は以下の通り。

  1. UITextFieldクラスを継承して、カスタムテキストフィールドクラスを作る(CustomTextFieldとする)
  2. Interface BuilderでCustomTextFieldをビューに配置する
  3. カスタムキーボードに相当する新しいxibファイルを、UIViewベースで作成する(CustomKeyboardInputViewとする)
  4. xibファイルをInterface Builderで起動し、入力選択肢(キーボードのキー)に相当するボタン(UIButon)を配置する
  5. 3. で作成したカスタムキーボードに対するビューコントローラクラスを作成する(CustomKeyboardInputViewControllerとする)
  6. 5. で作成したビューコントローラを、4. で作成したxibでFile’s Ownerに対するビューコントローラに設定する
  7. 1. で作成したCustomTextField.mを編集し、inputViewメソッドをオーバーライドする。このメソッドで、3.で作成したxibを使ってビューコントローラ(4.で作成したCustomKeyboardInputViewController)を生成し、そのビューコントローラに対するビューを戻す
  8. CustomKeyboardInputViewController.mを編集し、ビュー上のボタンが押された際のメソッドを記述し、呼び出し元となったカスタムテキストフィールド(CustomTextField)に適切な値をセットする

当然ながら、Interface Builderではなくプログラムでガリガリ書いても同じ(はず)。

この手法の考え方としては、UITextFieldやUITextView(を継承したサブクラス)のinputViewメソッドをオーバーライドして、新たに定義したキーボード(のUIView)を返すようにすれば、カスタムキーボードを表示できる、というものである。

一旦キーボードを表示してしまえば、あとは通常のビュー間でのデータのやりとりと同じ手法で、カスタムキーボードの呼び出し元になったテキストフィールドに、カスタムキーボードで選択したボタンに相当する値をセットしてやればよい。

サンプルソースは以下の通り。
本筋とは関係ない処理は全て削ってある。
本来は、本来のキーボードと切り替えるためのAccessoryViewを作ったり、その切り替え処理を組み込んだり、キーボードで選択したボタンに対する処理など、色々とやることはあるのだが、それらは除外した。

CustomTextField.h

#import 

@interface CustomTextField : UITextField {

}

@end

CustomTextField.m

#import "CustomTextField.h"
#import "CustomKeyboardInputViewController.h"

@implementation CustomTextField

- (UIView *)inputView {
	CustomKeyboardInputViewController *vc = [[CustomKeyboardInputViewController alloc] initWithNibName:@"CustomKeyboardInputView" bundle:nil];

	return vc.view;
}

- (void)dealloc {
    [super dealloc];
}

@end

カスタムキーボード呼び出し元になるxibの設定

カスタムキーボード表示対象のテキストフィールド(上で作成したCustomTextField)をビューに配置する。

カスタムキーボード自体のxib

実行結果

ビュー上のテキストフィールドを選択すると、カスタムキーボードが表示される。

キーボード選択値をテキストフィールドに設定

キーボードでのボタン選択で、テキストフィールドに値をセットするためには、カスタムキーボードのビューコントローラでボタンの処理を実装する。例えばこのようになる(テキストフィールドのプロパティをキーボードのビューコントローラ側に持たせるのはあまり良いやり方ではない気がするが、とりあえずそこは無視)。

まず、CustomKeyboardInputViewController.h で、対象テキストフィールドとボタンの処理を宣言。

#import 

@interface CustomKeyboardInputViewController : UIViewController {
	UITextField *tf;
}

@property (nonatomic, retain) UITextField *tf;

-(IBAction) btPressed:(id) sender;

@end

CustomKeyboardInputViewController.m で、ボタンの文字列をテキストフィールドにセットする。

#import "CustomKeyboardInputViewController.h"
#import "CustomKeyboardTestViewController.h"

@implementation CustomKeyboardInputViewController

@synthesize tf;

-(IBAction) btPressed:(id)sender {
	// キーボード上のボタン選択値をテキストフィールドにセット
	UIButton *bt = (UIButton *) sender;
	[self.tf setText:bt.titleLabel.text];
	
	// キーボードを隠す
	[self.tf resignFirstResponder];
}

@end

カスタムテキストフィールドのメソッドを少し変えておく。

#import "CustomTextField.h"
#import "CustomKeyboardInputViewController.h"

@implementation CustomTextField

- (UIView *)inputView {
	CustomKeyboardInputViewController *vc = [[CustomKeyboardInputViewController alloc] initWithNibName:@"CustomKeyboardInputView" bundle:nil];
	
	vc.tf = self; // これを追加
	
	return vc.view;
}

- (void)dealloc {
    [super dealloc];
}

@end

キーボードのxibを編集して、各ボタンからの処理を呼出すようにする。

7月
6

iOS4以降でのビュー切り替えとアニメーション

Author msota    Category 逆引き備忘録     Tags

ビューを切り替える場合(に限らないが)のアニメーション記述方法がiOS4から変更になった。ネットで探してみても、iOS4以降の記述方法があまり見つからなかったのでメモしておく。

結果的にはかなりシンプルになっている。
長いので改行しているが、ビューの切り替えも含めて、1文で終わってしまう。

ちなみに以下のoldVC、newVCは、変更前後のビューに対するビューコントローラ。

iOS4以降の場合

	[UIView transitionFromView: oldVC.view
		toView: newVC.view
		duration:0.5 
		options:UIViewAnimationOptionTransitionCurlDown
			completion:^(BOOL finished){
				/* do something on animation completion */
	} ];

(参考)iOS3.xまでの場合

	// アニメーション
	[UIView beginAnimations:@"flipping view" context:nil];
	[UIView setAnimationDuration:1];
	[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
	[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown 
							   forView:self.view cache:YES];

	// Change View
	[oldVC.view removeFromSuperview];
	[self.view addSubview:newVC.view];
	
	[UIView commitAnimations];
7月
4

SQLite+FMDBで日付型を扱う場合の注意点

Author msota    Category 逆引き備忘録     Tags

忘れないように整理しておく。

SQLiteとFMDBで日付型を扱う際の前提

まず、整理の前提となる事実。

  • SQLiteでは日付型そのものの型はないので、日付を格納する列はtextやrealで代替定義している
  • FMDBは日付型を扱うためのメソッドを提供しているが、列定義がrealであることを想定している
  • FMDBは、real値を日付型として返すために NSDate クラスの dateWithTimeIntervalSince1970 を利用している
  • FMDBは、real値を日付型としてSQLiteに登録するために NSDate クラスの timeIntervalSince1970 を利用している
  • 日付情報はUNIX時間(1970年1月1日を起源とした差分値)で管理している。NSDateクラスには、その前提で倍精度数値データを扱うためのメソッドがある(dateWithTimeIntervalSince1970 / timeIntervalSince1970)

対応方針

上記の前提を踏まえると、SQLite, FMDBの組合せでアプリケーションを組む場合は、以下のような方針にすれば良さそうだ。

  • SQLiteのテーブル定義時は、日付を扱う列はreal型で定義する
  • FMDBで日付型データを参照する場合は dateForColumn / dateForColumnIndex を使う(NSData型の値が戻される)
  • FMDBで日付情報を登録/更新する場合は、NSDate型にしておけば、あとはFMDBが勝手にやってくれる

実際にはNSDateFormatterで書式を整えたりする必要があるが、FMDBやSQLiteとは直接関係ないのでとりあえず考えないでおく。

問題点

テストデータを事前に手操作なり何なりでDBに登録しておきたい場合、timeIntervalSince1970 なり何なりで変換したreal値を登録しなければならない。ごく普通に「2011/06/20」のような値を登録できない。

6月
18

UITableViewでセル再描画時に文字が重ならないようにする

Author msota    Category 逆引き備忘録     Tags

セルをカスタマイズしたUITableViewを作成し、シミュレータで動かしてみると、上下にスクロールして再描画する際に、何の関係もないセルの値が別のセルに再描画されて、文字の上に文字が幾重にも重なり、凄いことになってしまった。それを回避するためには、セル内容作成メソッド cellForRowAtIndexPath で、サブビューを一旦取り除くことで対応できる。

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
static NSString *CellIdentifier = @"Cell";
    
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// ここまでデフォルトのまま。
    
// サブビューを取り除く
for (UIView *subview in [cell.contentView subviews]) {
	[subview removeFromSuperview];
}