久しぶりに UITableView のコードを書いて忘れていた点をメモ

UITableView のセルを制御するために色々なインデックス値などを保持しているコードをたまに見かけますが、できる限り余計なインデックス値などはメンバ変数として保持したくないものです。
コードで取得できるインデックスはコードで取得できた方が良いでしょう。
以下のメソッド忘れてました。(>_<)

1
[self.tableView indexPathForCell:cell];

参考: UITableViewCell 上に配置した UIControl のアクションから indexPath を取得する

あと、UITableViewCell に addSubview する場合は、

1
[cell.contentView addSubview:button];

を使用しましょう。

参考: Custome UITableViewCellの[self addSubview]と[self.contentView addView]の違い

久しぶりにコード書いて忘れてたので、メモです。

ナビゲーションバーもビューで覆う方法

ビューを全画面に表示しようとして、ナビゲーションバー上までビューが覆い被せることができず少し迷った。
window に addSubview すれば以下の画面のようにナビゲーションバー上までビューを覆い被せることが出来る。

1
2
3
4
5
6
LockViewController *lockView;
lockView = [[LockViewController alloc] init];
lockView.view.frame = CGRectMake(0, 0, 320, 480);
 
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.window addSubview:lockView.view];

iPhone

OS X 10.8.4 アップデート後 xcode シミュレータ実行時エラーの対処方法

OS X 10.8.4 にしてから、xcode からシミュレータ実行した際にエラーが出力されて困っていたが、一時的な対処方法が紹介されていた。
再実行 (⌘+R) でエラーでまくりで困ってたんですよ。(^^)

とりあえず、以下の記事の内容の通り、デバッガを LLDB から GDB に変更。

参照:OS X 10.8.4でXcodeでiOS Simulatorを実行したときにSIGABRTでアプリがクラッシュすることがある問題の暫定的な対処

追記: 6/14 Xcode 4.6.3 がリリースされており、問題も対処されているようです。

CoreData データベースにマスタデータを取り込む方法

iOS アプリで SQLite のマスタデータをデータベースに用意することに少し苦労したので、メモしておく。

iOS アプリで生成した SQLite データベースのテーブル構成を SQLite database browser で確認した。

・CoreData のテーブルには、テーブル名に"Z"が付加されている
・テーブル カラムにも"Z_PK", "Z_ENT", "Z_OPT" などの制御カラム(?)が追加されている

上記制御カラムの生成ルールがよくわからなかったので、CoreData データベースへのデータ追加は CoreData プログラムコードで行うこととした。
(他にいい方法はないのものか?)

1. 自作のCSVデータ取り込みアプリ(CoreData)でデータをインポート

CSVデータ取り込みアプリの .xcdatamodel にマスタテーブルを定義する
マスタテーブルへデータを取り込めるように改変する
マスタ データを取り込む

2. アプリで利用するSQLiteデータベースへデータをコピー

1
2
3
4
5
6
7
8
$ sqlite3 アプリのデータベース ファイル名.sqlite
sqlite> attach database 'マスタを保持したデータベース ファイル名.sqlite' as old;
sqlite> .database
sqlite> begin;
sqlite> insert into main.テーブル名('Z_ENT', 'Z_OPT', …カラム名) select Z_ENT, Z_OPT, …カラム名 from old.テーブル名; 
注意点: Z_PK などのプライマリキーは指定できない
sqlite> commit;
sqlite> .exit

3. NSBundle からデータベースをコピー

マスタデータを含むデータベースを xcode プロジェクトに追加しておき、アプリ起動時に以下のコードでコピーする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#pragma mark - Application's documents directory
 
// アプリのドキュメント ディレクトリ パスを返す
- (NSString *)applicationDocumentsDirectory
{    
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
    return basePath;
}
 
- (void)setupSqliteDb
{
    // SQLiteデータベース を保存するパスを取得する
    NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"BikeMaintenance.sqlite"];
    NSFileManager *fileManager = [NSFileManager defaultManager];
 
    // SQLiteデータベースが存在しない場合、作成する
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"BikeMaintenance" ofType:@"sqlite"];
        if (defaultStorePath) {
            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
        }
    }
}

サウンド ファイルのフォーマットを変換する方法

(コマンド書式)
/usr/bin/afconvert -f ファイルフォーマット -d コーデック [入力ファイル] [出力ファイル]

wav → caf 形式への変換方法
$ afconvert -f caff -d LEI16 input.wav output.caf

mp3 → caf 形式への変換方法
$ afconvert -f caff -d ima4 input.mp3 output.caf

フォーマット一覧を参照する
$ afconvert -hf

MagicalRecord を使用する方法

xcode 4.6.2 にて確認した。
xcode ってバージョンが変わると操作手順が変わることがあり、久しぶりに操作するときれいさっぱり忘れていることがあるので、メモ。

1. <プロジェクト名>.xcdatamodeld ファイルを作成する

2. CoreData エンティティを基にモデルクラス ファイルを作成する (( エンティティ名).h / .m)
NSManagedObject

3. mogenerator でカスタム クラス ファイルを作成する (_(エンティティ名).h / .m)
上記2.で作成したクラスを基に _”アンダーバー”が付加されたファイルが出力される。
出力されたファイルはプロジェクトに追加する。
(例) aaa.h → _aaa.h ファイルが作成される

Model ディレクトリに mogenerator が作成するファイルを出力する場合の例 (ARC対応)

1
2
3
mogenerator --template-var arc=true -m Model/(プロジェクト名).xcdatamodeld/(プロジェクト名).xcdatamodel/ -O Model/
 
(ARC対応しない場合は、--template-var arc=true は不要)

4. プリコンパイル ヘッダに MagicalRecord のヘッダを追加する

1
2
3
4
5
6
7
8
#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
 
    // MagicalRecord 用
    #define MR_SHORTHAND 1
    #import "CoreData+MagicalRecord.h"
#endif

5. CoreData.framework を追加しておく

参照: CoreDataをActiveRecord風に扱えるMagicalRecordの使い方

iOS6 で推奨されてなくなっているメソッド

deprecatedなメソッドがあるようなので、気づいたタイミングで対処。
モーダルビュー画面遷移のコードが推奨されなくなっていたので、新しいメソッドを利用するようにした。

1
2
3
4
5
6
7
 'presentModalViewController:animated:' is deprecated: first deprecated in iOS 6.0
 
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion NS_AVAILABLE_IOS(5_0);
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion NS_AVAILABLE_IOS(5_0);
 
[self presentViewController:(ビューコントローラ) animated:YES completion: nil];
[self dismissViewControllerAnimated:YES completion:NULL];

“Application windows are expected to have a root view controller at the end of application launch” がログに出力された場合の対処方法

iOS 4 以降は、UIWindow の rootViewController プロパティで、ビューコントローラを直接指定する方法が推奨されているとのこと。
iOS 6 SDK で以前の方法を使うと、画面の回転が正しく効かないなど不具合の原因となるらしい。

1
2
3
4
5
6
7
8
9
10
11
// iOS 6 以降の推奨
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 :
(省略)
 :
    self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:(UIViewController を指定する)];
 
    [self.window makeKeyAndVisible];
    return YES;
}

参照: 既存プロジェクトの iOS 6 SDK 移行

xcode 多言語対応の方法 (Version 4.6.1)

xcode の多言語対応手順についてメモしておく。
多言語対応の仕組みは知っていたが、いざ実際に行ってみると”Info.list”と”Localizable.strings”ってどう違うの?とか、xcode の ファイルインスペクタ操作などで疑問がでてきたので、まとめた。

1. xcode 設定を多言語対応する
“project” – “Info” の Localizations に “Japanese” を追加する

Localizations_1
・ローカライズ対象ファイルが多言語対応化される
・English と Japanese 用のファイルが用意される
以下のフォルダが作成されてそれぞれに多言語対応されたファイルが格納される
en.lproj
ja.lproj
Localizations_2
例えば、InfoPlist.strings (アプリ設定ファイル) をローカライズすればアプリ名称なども多言語対応することができる

/* Localized versions of Info.plist keys */
CFBundleDisplayName = "日本語アプリ名"; 

2. ソースコードを多言語対応する

書式: NSLocalizedString(@”キー”, @”コメント”)

NSBundle.h に以下のように定義されている

1
2
#define NSLocalizedString(key, comment) \
	    [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]

多言語対応例

1
2
3
4
5
// 変更前 (Localizations - English)
self.title = @"Detail";
 
// 変更後 (Localizations - English)
self.title = NSLocalizedString(@"Detail", @"Detail");

3. genstrings コマンドで言語ファイル生成

$ genstrings -a $(find . -name "*.m")

4. Localizable.strings の言語を指定する
3. で出力された Localizable.strings ファイルを xcode に追加し、言語を指定する
“File Inspector”を表示し、以下のボタンを押下する
Localizations_3
Localizable.strings ファイルの内容 (日本語リソースの場合)

1
2
3
4
5
/* Detail */
"Detail" = "詳細";
 
/* Master */
"Master" = "マスタ";