ラベル Xcode4 の投稿を表示しています。 すべての投稿を表示
ラベル Xcode4 の投稿を表示しています。 すべての投稿を表示

2011年5月22日日曜日

[iOS] Webサイトと通信してみる

前回、UINavigationControllerで階層的に画面を切り替える (2)

Webサイトと通信することで、ゲームのスコアやデータなどをやりとりすることができます。通信には非同期と同期の2種類がありますが、ここでは通信が終わるのを待たない非同期型の通信プログラムを作成します。

■最初に通信の流れ
1.Webサイトに送るデータを作成する
2.Webサイトにデータを送る
3.Webサイトからのデータを受け取る
4.データを文字列に変換する


■通信プログラムを作成する
1.Webサイトに送るデータを作成する
Webサイトと通信するには、NSURLConnectionクラスを利用しますが、先にWebサイトに送るデータを作成します。作成するには、NSMutableURLRequestクラスを使います。次のようにして、通信先とリクエストタイプを設定します。
NSMutableURLRequest *req =
    [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"通信先(http://.../)"]];
[req setHTTPMethod:@"リクエストタイプ(GETかPOST)"];


2.Webサイトにデータを送る
NSURLConnectionクラスに、作成したNSMutableURLRequestを渡します。
NSURLConnection *connection =
    [NSURLConnection connectionWithRequest:req delegate:<イベント通知先>];


2番目のdelegateに通信中に起きたイベント受け取るオブジェクトを指定する必要があります。このオブジェクトは、NSObjectを継承していて、受け取りたいイベントに関連するメソッドをオーバーライドしてください。少なくとも次のメソッドはよく使います。他にもメソッドはありますが、ここでは省略します。
●最初のレスポンス受信時に1度だけ呼ばれ、受信の初期化処理を行う
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
● 受信完了まで断片的にデータを受信する
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData;
● 受信完了時に1度だけ呼ばれます
- (void) connectionDidFinishLoading:(NSURLConnection *)connection;
● 通信エラー時に呼ばれます
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
●最初のレスポンス受信時に1度だけ呼ばれ、受信の初期化処理を行う
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

3.Webサイトからのデータを受け取る
Webサイトからのデータは、データサイズや通信状況により、部分的に送られてきます。データの受信を格納するには、NSDataクラスを継承したNSMutableDataクラスを使います。NSMutableDataクラスは、データを格納するNSDataクラスとは違い、中身のデータを編集することができます。通信が始まる前に、NSMutableDataクラスを初期化しておき、次のメソッドが呼ばれた際に、NSMutableDataにどんどんデータを追加していきます。
● 受信完了まで断片的にデータを受信する
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData;
NSMutableDataクラスの末尾にデータを追加するには、次のようにメソッドを利用します。
- (void)appendData:(NSData *)other;
要するに、
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData{
    // 通信前に初期化すること、NSMutableData *_data = [[NSMutableData alloc] init];
    [_data appendData: receiveData]
}

となります。

4.データを文字列に変換する
NSMutableDataをNSStringに変換するには、NSStringのinitWithDataメソッドを使います。
※ここでは、データはUTF8のエンコードであることを想定しています。
// NSMutableData *_data = [[NSMutableData alloc] init];
NSString *output = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];


■通信用のサンプルプログラムを作ってみた
ところどころに動作確認のために、コンソールにログをはき出すプログラムを入れています。
//  RunpetaConnection.h
//  runpeta
//
//  Created by くまころ on 11/5/22.
//  Copyright 2010 Runpeta. All rights reserved.
//
#import <Foundation/Foundation.h>

@interface RunpetaConnection : NSObject
{
@private
NSURLConnection *_connection;
    NSMutableData   *_data;

}
- (void) loadFromUrl: (NSString *)url method: (NSString *) method;

@end


//
//  RunpetaConnection.m
//  runpeta
//
//  Created by くまころ on 11/5/22.
//  Copyright 2010 Runpeta. All rights reserved.
//
#import "RunpetaConnection.h"

@implementation RunpetaConnection
// 最初のレスポンス受信時に1度だけ呼ばれ、受信の初期化処理を行う
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
   [_data setLength:0];
    NSLog(@"(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response");
}
// 受信完了まで断片的にデータを受信する
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData
{
    [_data appendData:receiveData];
    NSLog(@"(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData");
}

// 受信完了時に1度だけ呼ばれます
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"(void) connectionDidFinishLoading:(NSURLConnection *)connection");
 
    // 受信した内容を文字列に変換し、コンソールに出力する
    NSString *output = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
    NSLog(@"Output: %@", output);
    [output release];
}
// 通信エラー時に呼ばれます
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error");
}
//
- (void) loadFromUrl: (NSString *)url method: (NSString *) method
{
    NSMutableURLRequest *req =
      [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
   [req setHTTPMethod:method];
   _connection = [NSURLConnection connectionWithRequest:req delegate:self];
   _data = [[NSMutableData alloc] init];
}

- (void)dealloc {
    [_data release];
    [super dealloc];
}
@end


動作確認するために、実行される適当な場所にプログラムを追加しました。
RunpetaConnection *conn = [[RunpetaConnection alloc] init];
[conn loadFromUrl:@"http://runpeta.com/api/paneler" method:@"GET"];



・正常に動作した場合のコンソールログ
GNU gdb 6.3.50-20050815 (Apple version gdb-1518) (Sat Feb 12 02:52:12 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 14827.
Pending breakpoint 1 - ""RunpetaConnection.m":29" resolved
Pending breakpoint 2 - ""RunpetaConnection.m":44" resolved
Pending breakpoint 3 - ""RunpetaConnection.m":39" resolved
Pending breakpoint 4 - ""RunpetaConnection.m":51" resolved
Current language: auto; currently objective-c
2011-05-22 15:08:59.276 runpeta[14827:207] (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
2011-05-22 15:08:59.282 runpeta[14827:207] (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData
2011-05-22 15:08:59.283 runpeta[14827:207] (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)receiveData
2011-05-22 15:09:07.319 runpeta[14827:207] (void) connectionDidFinishLoading:(NSURLConnection *)connection
2011-05-22 15:09:07.323 runpeta[14827:207] Output:  <?xml version="1.0" encoding="UTF-8"?><paneler>
  <configs>
    <background_color>a9da8f</background_color>
    <background_image>http://runpeta.com/images/paneler/pl_bg.png</background_image>
    <border_color>a9da8f</border_color>
    <border_width>1</border_width>
    <foreground_color>ffffff</foreground_color>
    <padding_bottom>8</padding_bottom>
    <padding_top>8</padding_top>
    <padding_left>8</padding_left>
    <padding_right>8</padding_right>
   <auto_change_panel_time>5</auto_change_panel_time>
...以下、省略



■試しに、インターネットへの回線を切断して実行すると
きちんと通信エラーのメソッドが呼ばれていることが確認できました。
GNU gdb 6.3.50-20050815 (Apple version gdb-1518) (Sat Feb 12 02:52:12 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 15015.
2011-05-22 15:11:53.552 runpeta[15015:207] (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

[iOS] UINavigationControllerで階層的に画面を切り替える (2)

前回、UINavigationControllerで階層的に画面を切り替える

【開発環境】Xcode4、iOS4.3

ナビゲーションコントローラで新しくビューコントローラを開いてみます。ここでは、前回のテーブルビューコントローラの項目を選択したときに、再度テーブルビューコントローラを開くようにしてみます。

1.テーブルビューコントローラの項目を選択したときの処理を書く。[CourseListViewController.m]を開きます。CourseListViewController(テーブルビューコントローラ)のインスタンスを作成して、UINavigationControllerの[pushViewController]メソッドに渡すことで、新しくビューコントローラを開くことができます。
・ナビゲーションコントローラは、ビューコントローラの[navigationController]プロパティから参照できます。
・[animated]はアニメーションさせながら切り替えるかの属性です。
#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // (サンプル) 同じビューコントローラを新規に作成して開く
    CourseListViewController *viewCtrl = [[[CourseListViewController alloc] init] autorelease];
    [self.navigationController pushViewController:viewCtrl animated:YES];
}



2.あとナビゲーションバーに表示されるビューコントローラのタイトルを”Root View Controller"から変更する。[viewDidLoad]の中で、[title]プロパティに新しいタイトル名を代入します。
#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    // ビューコントローラのタイトルを付ける
    self.title = @"Course List";
 
    // 配列に文字列一覧を格納する
    item_ = [[NSArray alloc] initWithObjects:
                    @"DATA 1", @"DATA 2", @"DATA 3",
                    @"DATA 4", @"DATA 5", nil];
 
}


3.それでは、シミュレータを起動してみる。次のことを確認してみてください。
・タイトルが変わっていること
・項目を選択したときに、アニメーションして画面が変わること
・新しい画面のナビゲーションバーにあるボタンをクリックすると画面が戻ること




[iOS] UINavigationControllerで階層的に画面を切り替える


【開発環境】Xcode4、iOS4.3

UITabBarControllerの他に画面を切り替えるコントローラとして、UINavigationController(ナビゲーションコントローラ)があります。タブバーコントローラは、画面を並列的に切り替えるのに対して、ナビゲーションコントローラは画面を階層的に切り替えることができます。要するに、ユーザーの操作に応じて、新しく画面を開くことができ、また直前の画面に戻ることができます。


よく一覧表示の画面に使われています。画面上部にナビゲーションバーが表示され、直前の画面に戻るボタン現在の画面タイトルが表示されます。


ナビゲーションコントローラとタブバーコントローラは組み合わせて使うこともできます。ただ、タブバーコントローラの中にナビゲーションコントローラに使います。こんな感じになります。画面上部にナビゲーションバー、画面下部にタブバーコントローラが表示されています。

それでは、ナビゲーションコントローラを利用する手順について説明します。ここでは、前回までに作成したタブバーコントローラに追加する例を挙げます。

1.[MainWindow.xib]を開きます。左下の[→]のボタンをクリックして、画面に配置したオブジェクト一覧を表示させます。


2.↓のように画面内のオブジェクト一覧が表示されます。例えば、[Tab Bar Controller]の中に[UIViewController]が複数入っていることが分かります。


3.前回までは、[UIViewController]をタブバーところにドラッグして追加しましたが、今回は画面内のオブジェクト一覧から追加します。オブジェクトライブラリから[Navigation Controller]をドラッグします。


4.追加したナビゲーションコントローラを選択すると、画面内にナビゲーションバーが表示されていることが分かります。あと、左側の画面内のオブジェクト一覧を展開すると、[View Controller]を比べて、[Navigation Bar]と[View Controller]の2つが多いことが分かります。ここの[View Controller]を変更することで、最初に表示するビューコントローラを設定できます。


5.[View Controller]をカスタムビューコントローラに変更します。以前作成したカスタムテーブルビューコントローラに変えてみます。
①画面内のオブジェクト一覧から[View Controller]を選択します。
②アイデンティティインスペクターを開きます。
③[Class]でカスタムコントローラのクラスを選択します。
(ここでは”CourseListViewController”を選択します)


6.ついでにタブバーコントローラのアイコンも変えます。

①画面内のオブジェクト一覧から[Tab Bar Item]を選択します。
②アトリビュートインスペクターを開きます。
③[Title](ラベル)と[Image](画像)を変更します。




6.ここまででシミュレータを起動してみる。


次回、ナビゲーションコントローラで新しい画面を開く

2011年5月16日月曜日

[iOS] カスタムUITableViewControllerをつくる (3)

前回、カスタムUITableViewControllerをつくる (2)

テーブルビューのセルが選択されたときの処理を書く。セルが選択されたときには、
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPathが呼ばれるため、オーバーライドして処理内容を書く。


例えば、セルを選択したときに、セル内容をアラートに表示するサンプルを作成してみる。

1.[CourseListViewController.m]を開き、次のコードを追加する。
アラートを表示させるには、[UIAlertView]クラスを使います。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // セルが選択された時の処理を書く
    NSString* message = [item_ objectAtIndex:indexPath.row];
 
    UIAlertView* alert = [[[UIAlertView alloc] init] autorelease];// インスタンスの作成
    alert.message = message;// 表示メッセージの設定
    [alert addButtonWithTitle:@"OK"];// [OK]ボタンの追加
    [alert show];// アラートを表示する
}


2.シミュレータを実行してみると、きちんとアラートが表示されました。

実際はアラートより画面の切り替えなどを行うアプリの方が多い。
画面の切り替えについては、今度考えてみる。

次回、UINavigationControllerで階層的に画面を切り替える

2011年5月15日日曜日

[iOS] カスタムUITableViewControllerをつくる


【開発環境】Xcode4、iOS4.3

今度は、↓のテーブルビューコントローラをカスタムしてみます。
どちらもテーブルビューで、2種類のスタイルがあります。


プロジェクトに、”カスタムUIViewControllerをつくる”を参考に、テーブルビューコントローラ(UITableViewController)のサブクラスを追加します。サブクラス指定の画面で、UITableViewControllerを選択してください。クラス名には任意の名前をつけてください。ここでは、CourseListViewControllerと呼びます。


カスタムUIViewControllerをつくる”と同様に、[MainWindow.xib]を開き、タブバーコントローラに新しく作成したテーブルビューコントローラ(UITableViewController)のサブクラスを追加します。


[CourseListViewController.xib]を開き、[Aributes Inspector]を選択します。[Bottom Bar]の値を[Tab Bar]に変更します。実際はタブバーコントローラの高さ分画面が狭くなるので、仮にタブバーコントローラを表示させておきます。


ここまででシミュレータを起動してみる。当然、テーブルビューに何もデータを入れていないので空っぽですね。



次回、カスタムUITableViewControllerをつくる (2)

2011年5月5日木曜日

[iOS] タブバーコントローラにカスタムアイコンをつける

前回、カスタムUIViewControllerで画面の中を制御する (2)

【開発環境】Xcode4, iOS4.3

タブバーコントローラのアイコンをカスタムアイコンに変えてみよう。
サンプルは、走ってる人の絵っぽくした。


■カスタムアイコンにする前に、iOSに標準で用意されているアイコンに変えてみる。
1.プロジェクトナビゲータから[MainWindow.xib]を選択します。
①タブの部分に2回クリックすると、タブアイコンが選択されたことになります。
②[-▼-](Attributes inspector)をクリックします。コントローラの属性設定の画面が表示されます。
③[Identifier]でお好きなアイコンを選択してください。
※アイコンを選ぶと自動的に、タブのラベルも変わります。



■カスタムアイコンの画像を作成する
タブバーコントローラに利用できる画像は、色合い(RGB)は関係なく、ピクセルの透明度(アルファ値)が関係します。透過部分は非表示されず、非透過部分は表示されます。

1.GIMPを使います。画像を白・黒で描きます。
黒部分を透過、白部分を非透過にします。

2.メニューから[レイヤー]-[透明部分]-[色を透明度に...]を選択します。

3.透明にする色を選択して、[OK]ボタンをクリックします。

4.黒部分が透明になります。

5.完成した画像を2種類サイズに拡大・縮小します。
PNG形式で、***の部分はファイル名は自由につけてください。
・***.png :32x32
・***@2x.png :64x64(Retina用)

■作成したカスタムアイコン用の画像をプロジェクトに追加する
1.プロジェクトナビゲーターに作成した画像をドラッグします。

2.ファイルの追加方法をダイアログが表示されるので、そのまま[Finish]ボタンをクリックします。プロジェクトフォルダ内に画像の複製が追加されます。

■タブバーコントローラのアイコンを変更する
前半で、アイコンをiOS標準の画像に変えたように、タブバーコントローラのタブを選択します。
①[Title]に自由にタブ名を入力します。
②[Image]で作成した画像を選択します。

起動すると、アイコンが青色っぽくと輝いていると思います。選択時と非選択時で、表示のされかたが違うの試してみてください。


2011年4月23日土曜日

[iOS] カスタムUIViewControllerで画面の中を制御する (2)

前回の続き、カスタムUIViewControllerで画面の中を制御する (1)

【開発環境】 Xcode4, iOS4.3

スイッチを操作すると、コンソールにログを出力するところまで作成しました。
今回は、スイッチを操作した際に、ラベルの文字列を変えてみましょう。


■ラベルをプログラムから操作できるように、変数に関連づけます。
1.[〜ViewController.h]を開きます。赤枠のようにプログラムを追加します。
インスタンス変数「_label」、プロパティの宣言「label」を追加します。
※プロパティにIBOutletという識別子は、プログラム的に特別な意味はなく、Interface Builderからプロパティを利用する際に指定します。


2.[〜ViewController.m]を開きます。@implementation 〜ViewControllerの次ぐらいに、赤枠のようにプログラムを追加します。
プロパティをインスタンス変数と関連づけて実装します。
プロパティ「label」を通じて、インスタンス変数「_label」を操作することができ、クラス内部をカプセル化(隠蔽化)することができます。


3.[〜ViewController.xib]を開きます。作成したプロパティとラベル(UILabel)を関連づけます。
①[File's Owner]を選択します。
②[Connections Inspecter]をクリックします。[〜ViewControllerクラスで利用できるアウトレット(プロパティ)とアクション(メソッド)一覧が表示されます。
③[label]アウトレットをラベルまでドラッグします。


関連づけれると、このように変わりますが。


これでプログラムからラベルを操作できるようになります。

■スイッチを操作した時に、ラベルの文字列を変えてみる
1.前回作成したメソッドの中に次ぎのようにプログラムを追加します。


・メソッドの引数[sender]は、イベント発生元のスイッチであるので、変数型をキャストして、UISwitch(スイッチ)の型に変換します。
・スイッチの状態を知るには、UISwitchのプロパティ[on]を利用します。
・ラベルの文字列を変えるには、UILableのプロパティ[text]を利用します。


実行して、スイッチを操作してみると、ありゃ・・・ラベルの文字が小さすぎて見えない。

[〜ViewController.xib]を開き、ラベルを選択して、四隅の●をドラッグしてサイズを広げます。

これでバッチリラベルが表示されました。


2011年4月17日日曜日

[iOS] カスタムUIViewControllerで画面の中を制御する (1)

前回、カスタムUIViewControllerをつくる

[開発環境] Xcode4, iOS4.3

前回、作成したカスタムUIViewControllerの画面にスイッチとラベルを追加しました。
今度は、スイッチをON/OFFにすると、ラベルの内容が変わるようにしてみます。


さてプログラムを書いていきましょう。

■スイッチの状態(ON/OFF)が変わったときに呼ばれるメソッドを作ります。
1.[カスタムUIViewControllerの〜.h]を開き、メソッドを宣言します。「-(IBAction) <メソッドの名前>:(id)sender;」を追加します。メソッドの名前は自由につけれますが、引数と戻り値は合わせてください。senderには、イベントが発生したオブジェクトが入ります。今回は、UISwitchのオブジェクトです。


2.[カスタムUIViewControllerの〜.m]を開き、
「-(IBAction) <メソッドの名前>:(id)sender;」の定義を追加します。
末行あたりの@endの前くらいです。




■作成したメソッドをスイッチの状態が変わったときに呼ばれるようにする。
1.[カスタムUIViewControllerの〜.xib]を開き、
①で[File's Owner]を選択して、
②でコネクションインスペクターをクリックします。
③で作成したメソッドところで○をスイッチまでドラッグします。

2.ドラッグを離すと、スイッチのイベントが一覧が表示されます。[Value Changed]を選択します。

■ちゃんと呼ばれているかコンソールで確認してみる
1.作成したメソッドの中に、コンソールにログを出力する関数を追加します。
NSLog(@"〜出力するメッセージ");



2.アプリを実行する

3.コンソールを表示するには、Xcodeの下側にある[▲]ボタンをクリックします。

4.赤枠がコンソールです。

5.スイッチを押してみると、ログが表示されます。


次回、作成したメソッドの中で、ラベルの内容を変えるプログラムを追加してみます。

<補足>
「#pragma mark - 〜〜〜〜」って何だろう?
これを使うと、Xcodeでのメソッド一覧表示に見出しをつけてくれる





2011年4月16日土曜日

[iOS] カスタムUIViewControllerをつくる


[開発環境] Xcode4, iOS 4.3

カスタムUIViewControllerで新しい画面を作って、最初に作ったタブバーコントローラに追加します。

1.プロジェクト名のフォルダとこで、右クリックします。メニューが表示されるので、[New File...]をクリックします。


2.左エリアで[iOS]-[Cocoa Touch]を選択して、[UIViewController subclass]を選択します。[Next]ボタンを押します。


3.ここはそのままで、[Next]ボタンを押します。

4.カスタムUIViewControllerの名前をつける。".m"というのが、iOS開発で使うObjective-Cというプログラミング言語のソースファイルの拡張子になります。○○○ViewController.mとつけておけば、後から見たときに一目でUIViewControllerということが分かります。名前はなんでもいいです。[Save]ボタンを押します。


4.すると、3つファイルが追加されます。それぞれのファイルは、
・〜.h、〜.m:プログラムを書くファイル
・〜.xib:画面設計のファイル


5."〜.m"ファイルを選択すると、なにやらたくさん書かれています。よく使う機能がひな形として用意されています。



6."〜.xib"ファイルを選択すると、真っ白画面です。

 7.試しにスイッチとラベルを追加します。

8.[プロジェクトナビゲーション]から[MainWindow.xib]を選択します。前に作成したタブバーコントローラに追加します。作成したカスタムUIViewControllerは、UIViewController (View Controller)のサブクラスなので、仮にView Controllerをタブバーコントローラに追加しておきます。


9.[アイデンティティインスペクター]を開き、UIViewController (View Controller)に対応するUIViewControllerのクラスを変更します。さっき作成した"〜ViewController"を選択することで、このタブを選択したときにカスタムUIViewControllerの画面が表示されます。ここでは、Viewとしか表示されていませんが、実行するとちゃんと表示されます。



10.[→ Run]ボタンを押して、シミュレータを起動してみる。ちゃんとカスタムUIViewControllerの画面に置いた、スイッチとラベルが表示されています。



次回、カスタムUIViewControllerで画面の中を制御する (1)