データを作るプログラムを作る
プロジェクトの作成とInterface Builder上の作業
Xcodeで新規プロジェクトを作成します。タイプはCocoa Applicationです。使い捨てのプログラムなので名前は何でもよいのですが、JIS Color Makerとしました。
MainMenu.nibをダブルクリックしてInterface Builderを起動します。プロパティリストとstringsファイルを作成するだけですのでGUIは不要なのですが、何もないのもさみしいので最低限ウィンドウにテキストビューを一つだけ設けておきます。
nibウィンドウをclassesに切替えてNSObjectを選択し、右クリックしてサブクラスを作ります。名前はAppControllerとします。textViewという名前のアウトレットを追加してからインスタンス化して下さい。インスタンス化したAppControllerに、先ほどウィンドウに設けたテキストビューを接続しておきます。再びnibウィンドウをclassesに切替えてAppControllerを選択し、右クリックしてCreate Files for AppControllerを実行してソースファイルを作成すれば、Interface Builderでの作業は終わりです。
color_table.txtを読み取る
JISColorPicker.colorPickerフォルダの中にContentsフォルダがあり、その中にResourcesフォルダがあります。その中にあるcolor_table.txtというテキストファイルをドラッグして、JIS Color Makerのプロジェクトファイルに登録して下さい。場所はResourcesフォルダです。「必要ならコピーする」はチェックしてファイルをコピーするようにします。
リソースファイルにアクセスするにはNSBundleクラスを使います。バンドルとは関連ファイルをひとまとめにしたフォルダの事で、JISColorPicker.colorPickerフォルダの中にContentsフォルダがあり、その中にResourcesフォルダがあって・・・という構造がまさにバンドルになっています。実は普通のアプリケーションもそうは見えませんがバンドルになっています。アプリケーションのアイコンを右クリックして、「パッケージの内容を表示」というメニューコマンドを実行すれば、その構造を見る事ができます。
クラスメソッドmainBundleを使うと、アプリケーションのバンドルに関連づけられているNSBundleのインスタンスを取得できます。このインスタンス経由でリソースファイルにアクセスする事ができます。
まずはcolor_table.txtを読み込んで表示するところまでやってみましょう。リソースファイルを取り出すにはNSBundleのpathForResource:ofType:メソッドを使ってそのファイルのパスを取り出します。得られたパスをNSDataのdataWithContentsOfFile:メソッドに渡すと、NSData型のバイトデータが得られます。
バイトデータの中身はテキストファイルですから、NSStringのinitWithData:encoding:メソッドに渡す事でNSString型の文字列が得られます。color_table.txtはシフトJISでエンコードされていたので、NSShiftJISStringEncodingを指定する事で正しく読み込めました。この文字列をtextViewにセットする事で、得られた文字列が正常である事を確認できます。
- (void)awakeFromNib
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *fileName,*bodyText;
NSData *data;
fileName = [mainBundle pathForResource:@"color_table"
ofType:@"txt"];
data = [NSData dataWithContentsOfFile:fileName];
bodyText = [[NSString alloc] initWithData:data
encoding:NSShiftJISStringEncoding];
[textView setString:bodyText];
}
文字列を行に分解する
color_table.txtを読み取って、NSString型のインスタンスとして入手できました。次はここから必要な情報を読み取って、プロパティリストとstringsファイルを作成します。
まずはbodyTextを一行ずつバラバラにします。NSStringにはcomponentsSeparatedByString:メソッドがあり、渡した文字列を区切り文字として元の文字列を分解し、配列に入れて返してくれます。引数として改行文字を渡す事で、一行ずつバラバラにした配列を得る事ができます。
バラバラにしたら、次は一行ずつ処理していきます。
- (void)awakeFromNib
{
int i;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *fileName,*bodyText;
NSData *data;
NSArray *lines;
fileName = [mainBundle pathForResource:@"color_table"
ofType:@"txt"];
data = [NSData dataWithContentsOfFile:fileName];
bodyText = [[NSString alloc] initWithData:data
encoding:NSShiftJISStringEncoding];
[textView setString:bodyText];
lines = [bodyText componentsSeparatedByString:@"\r"];
for(i=0;i<[lines count];i++)
{
}
}
キー文字列と数値データを得る
キー文字列はNSStringのstringWithFormat:メソッドを使って生成します。"%03d"で000,001,002...という文字列が得られますが、この辺はC言語のprintfと同じです。
color_table.txtの中身は以下のようになっています。一行ずつバラバラにしたら、次はcomponentsSeparatedByString:メソッドにカンマを区切り文字として渡せば、項目ごとに分解する事ができます。
アイアンブルー,iron blue,2,80,50,0,50
あいいろ,藍色,1,70,20,0,60
あいねず,藍鼠,1,30,0,5,55
アイビーグリーン,ivy green,2,55,0,85,45
アイボリー,ivory,2,0,1,12,5
あお,青,1,100,3,0,10
あおたけいろ,青竹色,1,50,0,35,10
あおみどり,青緑,1,90,0,55,0
(以下略)
配列の添字はゼロから始まるので、シアンが3、マゼンタが4、イエローが5、ブラックが6になります。各文字列にintValueメッセージを送って整数値を得たら、その値でNSNumberオブジェクトを生成します。
- (void)awakeFromNib
{
int i;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *fileName,*bodyText,*key;
NSData *data;
NSNumber *cyan,*magenta,*yellow,*black;
NSArray *lines,*items;
fileName = [mainBundle pathForResource:@"color_table"
ofType:@"txt"];
data = [NSData dataWithContentsOfFile:fileName];
bodyText = [[NSString alloc] initWithData:data
encoding:NSShiftJISStringEncoding];
[textView setString:bodyText];
lines = [bodyText componentsSeparatedByString:@"\r"];
for(i=0;i<[lines count];i++)
{
key = [NSString stringWithFormat:@"color%03d",i];
items = [[lines objectAtIndex:i] componentsSeparatedByString:@","];
cyan = [NSNumber numberWithInt:[[items objectAtIndex:3] intValue]];
magenta = [NSNumber numberWithInt:[[items objectAtIndex:4] intValue]];
yellow = [NSNumber numberWithInt:[[items objectAtIndex:5] intValue]];
black = [NSNumber numberWithInt:[[items objectAtIndex:6] intValue]];
}
}
プロパティリストを作る
NSArrayはプロパティリストで使われるオブジェクトしか含んでいない場合、writeToFile:atomically:メソッドをつかってプロパティリストをファイルに書き出す事ができます。プロパティリストで使われるオブジェクトというのはNSString,NSArray,NSDictionary,NSData,NSNumber,NSDateです。今回使うのはNSString,NSArray,NSNumberだけなので、プロパティリストに書き出す事ができます。
したがって、NSMutableArrayに必要なデータを登録していき、最後にwriteToFile:atomically:メソッドをつかってプロパティリストをファイルに書き出せば、目的を達成できる事になります。NSMutableArrayはNSArrayのサブクラスなので、NSArrayのメソッドを使う事ができます。
キー文字列と各数値データをNSMutableArrayに追加するコードを追加します。プロパティリストはホームディレクトリにJISColor.plistという名前で作る事にします。
- (void)awakeFromNib
{
int i;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *fileName,*bodyText,*key;
NSData *data;
NSNumber *cyan,*magenta,*yellow,*black;
NSMutableArray *plist = [NSMutableArray array];
NSMutableArray *plistItem;
NSArray *lines,*items;
NSString *plistName = [NSString stringWithFormat:
@"%@/JISColor.plist",NSHomeDirectory()];
fileName = [mainBundle pathForResource:@"color_table"
ofType:@"txt"];
data = [NSData dataWithContentsOfFile:fileName];
bodyText = [[NSString alloc] initWithData:data
encoding:NSShiftJISStringEncoding];
[textView setString:bodyText];
lines = [bodyText componentsSeparatedByString:@"\r"];
for(i=0;i<[lines count];i++)
{
key = [NSString stringWithFormat:@"color%03d",i];
items = [[lines objectAtIndex:i] componentsSeparatedByString:@","];
cyan = [NSNumber numberWithInt:[[items objectAtIndex:3] intValue]];
magenta = [NSNumber numberWithInt:[[items objectAtIndex:4] intValue]];
yellow = [NSNumber numberWithInt:[[items objectAtIndex:5] intValue]];
black = [NSNumber numberWithInt:[[items objectAtIndex:6] intValue]];
plistItem = [NSMutableArray array];
[plistItem addObject:key];
[plistItem addObject:cyan];
[plistItem addObject:magenta];
[plistItem addObject:yellow];
[plistItem addObject:black];
[plist addObject:plistItem];
}
[plist writeToFile:plistName atomically:YES];
}
stringsファイルを作る
最後はstringsファイルです。これはプロパティリストの様に直接作るのではなく、stringsファイルにペーストするテキストファイルを作ります。英語環境用と日本語環境用の二つが必要です。
配列の添字2によって和名か外国名を見分けられます。ここが1なら和名、2なら外国名です。
和名の場合、英語環境用の情報はないのでデータ文字列は空白にしておきます。日本語環境用はデータ文字列として色名をつかい、読みの情報も追加します。
外国名の場合、英語環境用のデータ文字列は色名、日本語環境用のデータ文字列はよみになります。
したがって最終的にawakeFromNibメソッドは以下のようになります。フォーマット文字列の部分が見にくいかもしれませんが、これはフォーマット文字列の中でダブルクォーテーションを表す場合は\"としなくてはならないためです。
- (void)awakeFromNib
{
int i;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *fileName,*bodyText,*key;
NSData *data;
NSNumber *cyan,*magenta,*yellow,*black;
NSMutableArray *plist = [NSMutableArray array];
NSMutableArray *plistItem;
NSMutableString *stringsE = [NSMutableString string];
NSMutableString *stringsJ = [NSMutableString string];
NSArray *lines,*items;
NSString *plistName = [NSString stringWithFormat:
@"%@/JISColor.plist",NSHomeDirectory()];
NSString *stringsNameE = [NSString stringWithFormat:
@"%@/JISColorPlistE.txt",NSHomeDirectory()];
NSString *stringsNameJ = [NSString stringWithFormat:
@"%@/JISColorPlistJ.txt",NSHomeDirectory()];
fileName = [mainBundle pathForResource:@"color_table"
ofType:@"txt"];
data = [NSData dataWithContentsOfFile:fileName];
bodyText = [[NSString alloc] initWithData:data
encoding:NSShiftJISStringEncoding];
[textView setString:bodyText];
lines = [bodyText componentsSeparatedByString:@"\r"];
for(i=0;i<[lines count];i++)
{
key = [NSString stringWithFormat:@"color%03d",i];
items = [[lines objectAtIndex:i] componentsSeparatedByString:@","];
cyan = [NSNumber numberWithInt:[[items objectAtIndex:3] intValue]];
magenta = [NSNumber numberWithInt:[[items objectAtIndex:4] intValue]];
yellow = [NSNumber numberWithInt:[[items objectAtIndex:5] intValue]];
black = [NSNumber numberWithInt:[[items objectAtIndex:6] intValue]];
plistItem = [NSMutableArray array];
[plistItem addObject:key];
[plistItem addObject:cyan];
[plistItem addObject:magenta];
[plistItem addObject:yellow];
[plistItem addObject:black];
[plist addObject:plistItem];
if([[items objectAtIndex:2] isEqualToString:@"1"])
{
[stringsE appendFormat:@"\"color%03d\" = \"\";\r",i];
[stringsJ appendFormat:@"\"color%03d\" = \"%@\";\r"
,i,[items objectAtIndex:1]];
[stringsJ appendFormat:
@"\"color%03dPronunciation\" = \"%@\";\r"
,i,[items objectAtIndex:0]];
}
else
{
[stringsE appendFormat:@"\"color%03d\" = \"%@\";\r"
,i,[items objectAtIndex:1]];
[stringsJ appendFormat:@"\"color%03d\" = \"%@\";\r"
,i,[items objectAtIndex:0]];
}
}
[plist writeToFile:plistName atomically:YES];
[stringsE writeToFile:stringsNameE atomically:YES];
[stringsJ writeToFile:stringsNameJ atomically:YES];
}