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

0 件のコメント:

コメントを投稿