Cocoaアプリの起動までのプロセスとイベント処理の仕組み
この資料は内部で勉強用に作成したものでCocoa Programming for Mac OS Xの内容をベースにしております。Cocoaアプリの起動からユーザイベントの処理までの仕組みが記述されています。
この文書に含まれている一部図は同書、あるいはアップルのドキュメントから抜粋しておりますのであくまでも参考にだけ使ってください。なお、この文書の説明は概要までで止めております。より詳しい内容が知りたい場合は同書、あるいはアップルの資料を参考にしてください。
UIView to draw sweet graphs
iPhoneアプリでグラフを表示したいと思い使える物がないか検索してみました。
すると下記図のようなクールなグラフを簡単に描けるライブラリがありました。その名もs7graphview

使い方はとても簡単!
http://code.google.com/p/s7graphview/
上記リンクの右側にあるFeatured downloads:という所のs7graphview-basic-release.zipをダウンロードしてファイル一式を自分のプロジェクトに追加して使います。
ちなみに、DemoS7GraphView.zipというプロジェクトは私の環境では原因不明のエラーによりデモを実行してみることは出来ませんでした。
s7graphview-basic-release.zipを解凍すると下記のような3つのファイルが存在しており自分のプロジェクトの中で
#import "S7GraphView.h"することによりAPIを使えるようになります。
使い方はTableViewの実装と同様にグラフを描くためにUIVIewControllerでDataSourceを実装してあげるだけでグラフを描いてくれます。
まず、ヘッダーファイルで
#import "S7GraphView.h"
@interface TestViewController : UIViewController<S7GraphViewDataSource> {
S7GraphView *graphView;
}
@property (nonatomic, retain) S7GraphView *graphView;
のように宣言し
ソースフィアルで色やデータソースなどを設定し(使った後のメモリ解放処理も忘れないようにしましょう)
@synthesize graphView;
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
//self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.graphView = [[S7GraphView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = self.graphView;
self.graphView.dataSource = self;
//self.view.backgroundColor = [UIColor yellowColor];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSNumberFormatter *numberFormatter = [NSNumberFormatter new];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMinimumFractionDigits:0];
[numberFormatter setMaximumFractionDigits:0];
self.graphView.yValuesFormatter = numberFormatter;
NSDateFormatter *dateFormatter = [NSDateFormatter new];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
self.graphView.xValuesFormatter = dateFormatter;
[dateFormatter release];
[numberFormatter release];
self.graphView.backgroundColor = [UIColor blackColor];
self.graphView.drawAxisX = YES;
self.graphView.drawAxisY = YES;
self.graphView.drawGridX = YES;
self.graphView.drawGridY = YES;
self.graphView.xValuesColor = [UIColor whiteColor];
self.graphView.yValuesColor = [UIColor whiteColor];
self.graphView.gridXColor = [UIColor whiteColor];
self.graphView.gridYColor = [UIColor whiteColor];
self.graphView.drawInfo = NO;
self.graphView.info = @"Load";
self.graphView.infoColor = [UIColor whiteColor];
//When you need to update the data, make this call:
[self.graphView reloadData];
}
- (void)dealloc {
[graphView release];
graphView = nil;
[super dealloc];
}
DataSourceの中身を実装してあげるだけでグラフを表示してくれます。
#pragma mark -
#pragma mark end
#pragma mark protocol S7GraphViewDataSource
- (NSUInteger)graphViewNumberOfPlots:(S7GraphView *)graphView {
/* Return the number of plots you are going to have in the view. 1+ */
return 2;
}
- (NSArray *)graphViewXValues:(S7GraphView *)graphView {
/* An array of objects that will be further formatted to be displayed on the X-axis.
The number of elements should be equal to the number of points you have for every plot. */
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:101];
for ( int i = -50 ; i <= 50 ; i ++ ) {
[array addObject:[NSNumber numberWithInt:i]];
}
return array;
}
- (NSArray *)graphView:(S7GraphView *)graphView yValuesForPlot:(NSUInteger)plotIndex {
/* Return the values for a specific graph. Each plot is meant to have equal number of points.
And this amount should be equal to the amount of elements you return from graphViewXValues: method. */
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:101];
switch (plotIndex) {
default:
case 0:
for ( int i = -50 ; i <= 50 ; i ++ ) {
[array addObject:[NSNumber numberWithInt:i*i]]; // y = x*x
}
break;
case 1:
for ( int i = -50 ; i <= 50 ; i ++ ) {
[array addObject:[NSNumber numberWithInt:i*i*i]]; // y = x*x*x
}
break;
}
return array;
}
このようなすばらしいライブラリを作って頂いた作者に感謝です。m(__)m
NSTextField関連バグ?
今作成中のアプリに、一つのウィンドウの上に子ウィンドウとして新しいウィンドウを表示する部分があります。このウィンドウの内容を表示するためにNSObjectControllerでバインディングしたテキストフィールドを複数おいてますが、これらの表示に問題が。
最初に表示する分には問題がありませんが、どっかのフィルドをマウスでクリックして選択したままそのウィンドウを閉じてしまうと後でまた開いた時にそこの値が表示できない問題が発生しました。そのテキストフィルドを再びクリックすると値が表示されますが、他のフィルドをクリックするとまた値が表示されなくなります。
最初はバインディングの問題かと思い、色々いじってみましたが改善できず、ウェブにもそれらしき情報はありませんでした。
色々試していたところ、テキストフィールドの背景色を表示しない、また輪郭を書かないように設定するとこの問題が解消されることを確認。
今のところこの設定で問題ないのでこれで行こうとしていますが、これはNSTextFieldのバグでしょうか?
COCOAでのASIHTTPRequestとJSONの使い方
今回はCOCOAのHttp通信ライブラリASIHTTPRequestとJSONライブラリSBJONを紹介したいと思います。
ASIHttpRequest 英文ドキュメント
http://allseeing-i.com/ASIHTTPRequest/How-to-use
JSON
http://blog.zachwaugh.com/post/309924609/how-to-use-json-in-cocoaobjective-c
基本的な使い方は
NSURL *ns_url = [NSURL URLWithString:@“http://test.com”]; ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:ns_url]; [request setPostValue:user_id forKey:@“loginId”]; [request setPostValue:pass forKey:@“loginPass”];
ASIRequest ObjectにURLはtest.com、パラメタはpost形式の値を設定します。
同期(synchronous)の場合はrequestを送ってエラーがなかったらresposeを取得する処理を順次、記述します。
[request startSynchronous];
NSError *error = [request error];
NSString *response;
if (!error) {
response = [request responseString];
}else{
return false;
}
...
非同期の場合は
受信処理を行うデリゲートを設定して非同期的な処理を任せます。
主メッソドの例
※この場合はデリゲートとして自分を指定します。
[request setDelegate:self]; [request startAsynchronous];
デリゲートメソッドを実装
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
処理
........
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
エラー処理
........
}
STRINGデータをJSONに変換するには SBJSONを使います。
例)
SBJSON *json = [SBJSON new];
NSArray *statuses = [parser objectWithString:json_string error:nil];
[json release];
// Each element in statuses is a single status
// represented as a NSDictionary
for (NSDictionary *status in statuses)
{
// You can retrieve individual values using objectForKey on the statusNSDictionary
// This will print the tweet and username to the console
NSLog(@"%@ - %@", [status objectForKey:@"text"],
[[status objectForKey:@"user"] objectForKey:@"screen_name"]);
}
上記のようにjson_stringからDictionary Objectを生成して変換します。
実際のASIHTTPと連携したソースはこんな感じになります。
+ (NSArray *)scheduleWithId:(NSString*)user_id pass:(NSString*)pass date:(NSDate *)date {
//日付から年と月を取得
NSDateFormatter *outputFormatter = [[[NSDateFormatter alloc] init] autorelease];
[outputFormatter setDateFormat:@“yyyy-MM-dd”];
NSString *newDateString = [outputFormatter stringFromDate:date];
NSArray *dateArray = [newDateString componentsSeparatedByString:@“-“];
NSLog(@“current date : %@“,dateArray);
//URL及びパラメターを設定
NSURL *ns_url = [NSURL URLWithString:TEST_URL];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:ns_url];
[request setPostValue:user_id forKey:@“loginId”];
[request setPostValue:pass forKey:@“loginPw”];
[request setPostValue:[dateArray objectAtIndex:0] forKey:@“currentYear”];
[request setPostValue:[dateArray objectAtIndex:1] forKey:@“currentMonth”];
[request startSynchronous];
NSError *error = [request error];
NSString *response;
if (!error) {
//responseデータをTRIMする
response = [[request responseString] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//responseデータから特殊文字を処理 " -> \
response = [response stringByReplacingOccurrencesOfString:@“"” withString:@“\””];
}else{
return false;
}
NSLog(@“response : %@“,response);
SBJSON *json = [SBJSON new];
NSDictionary *statuses = [json objectWithString:response error:nil];
[json release];
NSLog(@“json : %@“,statuses);
// Each element in statuses is a single status
// represented as a NSDictionary
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:@“yyyy-MM-dd”];
NSArray *scheduleItems = [statuses objectForKey:@“scheduleItems”];
for (NSMutableDictionary *schedule in scheduleItems)
{
[schedule setObject:[dateFormatter dateFromString:[schedule objectForKey:@“startDate”]] forKey:@“startDate”];
[schedule setObject:[dateFormatter dateFromString:[schedule objectForKey:@“endDate”]] forKey:@“endDate”];
// You can retrieve individual values using objectForKey on the status NSDictionary
// This will print the tweet and username to the console
NSLog(@“title : %@ , contents : %@ , startDate : %@ , endDate : %@ “,
[schedule objectForKey:@“title”] ,
[schedule objectForKey:@“contents”] ,
[schedule objectForKey:@“startDate”] ,
[schedule objectForKey:@“endDate”]
);
}
return scheduleItems;
}
サーバからは
scheduleItems : {"title": “タイトル”, “contents”: “” , “startDate”:”2010-3-10” ,“endDate”:”2010-3-11”}
このような形式のデータか送られて来るので最初にDictionaryからscheduleItemsを取得し、
配列データを取得します。
AquaticPrimeでのライセンスメールの文字化け
AquaticPrimeはライセンスフレームワークで有名なオープンソースのフレームワークです。
Paypal及びKagiなどの決済サイトと連動しライセンスの自動発行も可能でサンプルソースも提供していますが、php阪のUNICODE対応にちょっと不具合があるので修正が必要です。
元ソース
AquaticPrimePayPal.phpの60行目
for ($i = 1; $i < count($lines); $i++)
{
list($lineKey, $lineValue) = explode("=", $lines[$i]);
$keyarray[urldecode($lineKey)] = urldecode($lineValue);
}
$product = $keyarray['item_name'];
$name = $keyarray['first_name']." ".$keyarray['last_name'];
$email = $keyarray['payer_email'];
$amount = $keyarray['mc_gross'];
$count = $keyarray['quantity'];
// RFC 2822 formatted date
$timestamp = date("r", strtotime($keyarray['payment_date']));
$transactionID = $keyarray['txn_id'];
// Create our license dictionary to be signed
$dict = array("Product" => $product,
"Name" => $name,
"Email" => $email,
"Licenses" => $count,
"Timestamp" => $timestamp,
"TransactionID" => $transactionID);
$license = licenseDataForDictionary($dict, $key, $privateKey);
元スースはurldecode後のデータをそのままライセンス発行とメール送信に使用しています。
しかしもしデータの中にASCII以外の文字列が入った場合には正しく動くという保証はありません。
UNICODE文字に対応する為には下記のような処理が必要です。
...
$name = convert_to($keyarray['first_name']." ".$keyarray['last_name'] , "UTF-8");
$base64_name = base64_encode($name);
.....
$dict = array("Product" => $product,
"Name" => $base64_name,
"Email" => $email,
"Licenses" => $count,
"Timestamp" => $timestamp,
"TransactionID" => $transactionID);
$license = licenseDataForDictionary($dict, $key, $privateKey);
convert関数
function convert_to ( $source, $target_encoding )
{
$encoding = mb_detect_encoding( $source, "auto" );
$target = str_replace( "?", "[question_mark]", $source );
$target = mb_convert_encoding( $target, $target_encoding, $encoding);
$target = str_replace( "?", "", $target );
$target = str_replace( "[question_mark]", "?", $target );
return $target;
}
まず 日本語の$name 属性はUTF-8に変換します、ライセンス発行ロジックには
UTF-8文字列をそのままでは使えない為、$name変数をbase64形式に変換します。
メールにはUTF-8にencodeした$nameを、ライセンス発行には$base64_nameを
使います。
AquaticPrime.php 196行目
function sendMail($to, $from, $subject, $message, $license, $name, $bcc='')
{
// Create a random boundary
$boundary = base64_encode(MD5((string)rand()));
$message = mb_convert_encoding($message,"ISO-2022-JP", "UTF-8");
最後にメール送信ヘッダにUTF-8のデータをISO-2022-JPの形式で変換して送信すれば完了です。
NSDateのTips
COCOA開発で日付の処理はよくある事です。
今日はいくつかの個人的Tipを共有します。
1. 日付間の日数を計算
#define TIME_INTERVAL_FOR_DAY 86400
// Calculate and return number of days between two dates.
+ (int) numberOfDaysBetween:(NSDate*)firstDate and:(NSDate*)secondDate {
NSTimeInterval interval = [secondDate timeIntervalSinceDate:firstDate];
// Add 1 for correct number of days
return (((int)interval) / TIME_INTERVAL_FOR_DAY)+1;
}
2. 日付に月を加算
//Add Month from Date
+ (NSDate *) date:(NSDate *)fromDate byAddingMonth:(int)monthOffset
{
NSDateComponents *month = [[NSDateComponents alloc] init];
[month setMonth:monthOffset];
NSDate *monthStartDateWithOffset =
[[NSCalendar currentCalendar] dateByAddingComponents:month toDate:fromDate options:0];
[month release];
return monthStartDateWithOffset;
}
3. 日付から一日のデータ取得
iPhoneの開発でデータを日付で絞って取得することはよくある処理でしょう。
※下記のソースはiPhone SDKでcore dataを使った場合です
- (NSArray *)dailyDataFromDate:(NSDate *)from_date {
NSCalendar *calendar= [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
//①
NSDateComponents *initComponents = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:from_date];
//②
NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init];
[componentsToSubtract setDay:+1];
NSDate *fromDate = [calendar dateFromComponents:initComponents];
NSDate *toDate = [calendar dateByAddingComponents: componentsToAdd toDate:fromDate options:0];
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"(timeStamp >= %@ ) and (timeStamp < %@)",fromDate,toDate];
//③
NSArray *matchingFetchedObjects = [fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:requestPredicate];
[calendar release];
[componentsToSubtract release];
return matchingFetchedObjects;
}
まず、①は日付の時刻を初期化するコンポーネントを生成して一日の始発時間を取ります。
②では一日を追加するコンポーネントを生成します。
③でArrayに①と②で取得した日付をフィルタリングを掛けてデータを取得します。
アップルのサイトを参考
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/DatesAndTimes/Articles/dtDates.html
Core Dataと(R)DBMSとは何が違うか?
例のCocoa With Loveに面白い記事が新しく追加されました。
The differences between Core Data and a Database
みんなのかゆいところをかいてくれるいい文章だと思います。私自身も最初にCore Dataを使い始めた時にまるでRDBMSを使うような感覚でオブジェクトグラフを設計していたのを今でも覚えています。
詳細は上記のリンクを読んで頂ければいいと思いますが、同記事を読んで私なりに理解したものを要約すると下記の通りです。
・DBMSはディスクにあるデータを最新の状態に保つためのものであるが、Core Dataはメモリ上のオブジェクトグラフを操作するためのものである。もちろん、Core Dataもデータのディスクへの保存やデータの取得、無欠性の保証をするが、それらはあくまでもサポート的な機能であり、そもそもの目的はオブジェクトグラフの管理と永続化である。
・DBMSは複数の使用者(プログラム)から共有されることを前提にしているがCore Dataは一つの使用者(プログラム)からの使用を前提にしている。(Core Dataは基本マルチスレッドに対応していない。ただし、マルチスレッドに対応させる方法もある。マルチスレッド対応については上記リンクの本文のコメントを参照すること)
・DBMSはトランザクションの概念があり常にディスクのデータを最新の状態に保つ。(DBMSの実装によって詳細は異なるが、少なくともプログラマにはそう意識される。)Core Dataはメモリ上のオブジェクトに対して行った変更を必要なタイミングでディスクに書き込む処理を行う必要がある。
・上記の特徴により、DBMSで大量の新しいデータを作成するよりCore Dataでする方が格段に早い。ただし、新しいデータ生成のタイミングでDBMSでは既にディスク上にもデータが存在し、システムのトラブルなどによる異常終了の際にもそのデータはちゃんと残るが、Core Dataでは新しいデータはメモリ上に存在しているだけなので異常終了の際にはそのデータは失われることとなる。これはデータの安全性とパフォーマンスからどちらをより大事にする設計思想なのかに起因すること。(ただし、Core Dataでメモリ上に生成した新しいデータを永続化する(SQLite, XML, FIleなどに書き込む処理)際にはCore Dataから永続化ツールに対する変換+永続化ツールの永続化処理の二重の処理負荷がかかり、DBMSのみを使う場合より遅くなる。)
・DBMSはテーブルの削除、WHERE句を使った絞り込みを行いその結果セットに対する操作など、個々のデータをメモリにロードせずに処理する、或は最小のデータセットのみに絞ってから処理することができる。Core Dataはメモリにロードしているデータ(オブジェクト)のみを操作できる。すべてのデータを削除したいのであれば対象データを先ずはすべてメモリにロードしないといけない。Core Dataで大量のデータを処理する際には常にメモリ使用量に対する考慮を必要とする。
・DBMSにはuniqueキーなど、データに対する制約をかけることができるがCore Dataではそのような仕組みはない。Core Dataで扱うオブジェクトは継承しオーバーライドすることができるのでそのような制約は無意味である。Core Dataを使うプログラムではデータに対する制約はプログラム側で責任を取る必要がある。
以上です。
残念なのは、私が最初にCore Dataを勉強した時にこのような文書があったらかなりの試行錯誤を防げたのになぜいまさら?ってことですが、まあ、それはさておき。
※上記は私の理解と思いが反映されたものなので、正しい内容は必ず本文を参考にしてください。
cocoaでのSingletons、Global values
私は最近iPhone用アプリ開発に励んでいますが、開発中によく直面する課題の一つは
各Controllerで共通に使う変数をどうやって実装するかということです。
今まではAppDelegateから各controllerの生成時に変数を渡す形にしていましたが、
必要な変数が増えるとその度入れないと行けないので冗長なパターンですね。
で、今回開発中に見つけたのがこれ
http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
いつも有難いcocoa with loveさんのブログですが
ここに良い方法がありました。
どんなApplicationでもAppDelegateは一つだけなので
そのAppDelegateを呼ぶことが出来ればまるでsingleton見たいに
利用することも出来ます。
AppDelegateを取得する方法は
cocoa
[NSApp delegate]
iPhone SDK [UIApplication sharedApplication].delegate
です。
例えば
iPhoneのUI ControllerにmanagedObjectContextを入れたい場合
下記のようにAppDelegateから直接入れるしかないため
AppDelegate.m UINavigationController *navController = [[tabBarController viewControllers] objectAtIndex:1]; [secondController setManagedObjectContext:self.managedObjectContext];
UIViewControllerが増える度にその作業をしないといけなくなります。
でもController側からAppDelegateの変数をゲットすることが出来たら
SecondViewController.m self.managedObjectContext = [(AppDelegate*)[UIApplication sharedApplication].delegate managedObjectContext];
上記のように自分が必要な時にObjectを取得する事も可能になります。
Singletonというのは便利な割には危ない所もありObject間の結合性を
高めることがありますが上手に使ったらシンプルなデザインにもなる両端の刃です。
cocoa with loveのブログにも書いてある通り、singletonはなるべく使わない方が良いものです。
使うときは本当に必要な所だけ限定的に使って下さい。
iPhone カレンダーライブラリの設置- TapkuLibrary
今日はiPhoneで有名なカレンダーライブラリ、TapkuLibraryのインストール方法を紹介します。
iPhone SDKではカレンダー機能を提供しないのでカレンダーは自分で手動で実装しなければなりません。
しかしゼロからカレンダーを作るという事はかなりの時間を要しデザイン及び機能追加など一筋縄では行かないと思います。
そこでネット上で公開されているTapkuLibrary というナイスなフレームワークを紹介します。
かなりキレイなUIを提供しています。
しかしインストール説明文が英語になっており間違っている所もありインストール手順も複雑だったため自分の経験を皆様と共有したいと思います。
インストール手順
1. TapkuLibraryをローカルに落とす。
まずダウンロードするにはGITクライアントが必要です。
$mkdir TapkuLibrary
$cd TapkuLibrary
$git clone git://github.com/devinross/tapkulibrary.git
2. TapkuLibraryを現在のプロジェクトにimportする。
srcの下にあるTapkuLibrary.xcodeprojファイルを現在のプロジェクトの最上端にDrag&Dropします。
オプションは
デスティネーショングループのフォルダに項目をコピーする : チェックなし
参照タイプ : プロジェクト基準
追加したフォルダに再帰的にグルプを作成する : チェック
で追加します
3. targetに追加
先ほど追加したプロジェクトの中に "libTapkuLibrary.a"があります。
右のディテールウインドウから'◎'項目にチェックを入れます。
4. 依存関係(dependency)追加

プロジェクトの下にあるTargetを開いて下さい。
下にある現在のプロジェクト名をダブルクリックして一般タブの直接依存関係画面に
'+'ボタンを押してTapkuLibraryを追加します。
5. TapkuLibrary.bundle追加
srcの下にあるTapkuLibrary.bundleを現在のプロジェクトに追加します。
オプションは
デスティネーショングループのフォルダに項目をコピーする : チェックなし
参照タイプ : プロジェクト基準
追加したフォルダにフォルダ参照を作成する : チェック
で追加します。
6. 既存フレームワーク追加
プロジェクトの下のFrameworksを右クリックして既存のフレームワークを選択します。
追加するフレームワークはQuartzCore.frameworkとMapKit.frameworkです。
7. 7. 最後にTapkuLibraryヘッダの追加

-プロジェクトの設定を開いてビルドタブをクリックします。
検索パスのヘッダ検索パスをダブルクリックしてTapkuLibraryのsrcディレクトリを指定します。

-リンクのリンカフラグをダブルクリックして"-ObjC"、"-all_load"を追加します。
8. 今後ソースコードの上で
#import <tapkulibrary /TapkuLibrary.h>
を追加することで簡単にTapkuLibraryのクラスを利用出来ます。
サンプルとして簡易実装してみました。
#import <UIKit/UIKit.h>;
#import <TapkuLibrary/TapkuLibrary.h>;
@interface TestViewController : UIViewController {
//カレンダービュー追加
TKCalendarMonthView *monthView;
}
@property (retain,nonatomic) TKCalendarMonthView
*monthView;
@end
------------------------------------------
実装クラス
#import "TestViewController.h"
@implementation TestViewController
@synthesize monthView;
- (void)loadView {
[super loadView];
//カレンダービュー初期化
monthView = [[TKCalendarMonthView alloc] init];
[self.view addSubview:monthView];
[monthView reload];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
if(monthView != nil) [monthView release];
[super dealloc];
}
@end
インストールに手間がかかりますがそれ以上の機能を提供してくれるので
カレンダーが必要な方は是非試して見て下さい。
Mac開発時の必須ツール
今日はMacでアプリケーションを開発するために使用するツールについて説明します。
Xcode

まずMacのアプリケーションを開発するための必須ツールとして、Xcodeがあります。Xcodeはプログラムのソースコード、イメージファイル、サウンドファイルなどのリソースの管理とソースコードを編集できるエディタとコンパイラー、そして実行及びデバッグが可能な環境を提供します。


編集ツールにはソースコード記述の間違いをチェックするsyntax check、変数及びメソッド名の候補を素早く表示してくれるコードアシスタント、code3.2から登場した静的分析(objectの使用状態を静的に追跡)によるメモリリーク検出など、円滑な開発の為の機能を沢山備えてあります。

そしてGCC,GDBが内蔵されているためバグが発生した時、原因を探す事も簡単です。
Interface Builder

アプリのGUIを生成する道具としてInterface Builderがあります。
Interface Builderから提供するライブラリを利用してウインドウを作ったり
ボタンを生成して配置することでプログラムのUIを制作することが可能です。

単純にUIを配置するだけではなく配置されたUI Ojbectの属性及びUI Ojbectの間の関係などを
設定することも出来ます。
Instruments

Instrumentsはプログラムの動作状態を最適化するツールです。
自分が作ったアプリがどのくらいメモリとCPU,DISKなどを使用しているかそして
無駄なメモリを使用していないかに関する情報をリアルタイムに収取しグラフと表などで
グラフィカルに表示します。
アプリの完成度を高めるためには必ず利用すべきツールです。
iPhone simulator

その他、iPhone用のアプリを開発するならiPhone simulatorの利用は必須です。
作成したiPhoneアプリをMacの中で動作させてUI及び一般的な機能のテストを行えます。
(GPS,音声入力、加速度センサーなどは実機でのみテスト可能です)
以上で開発に必要な必須的なツールを簡単だけでも説明しました。
上記ツールを自由自在に使いこなせる事によって飛躍的に生産性アップを望めます。



