COMPANY SERVICE STAFF BLOG NEWS CONTACT

STAFF BLOG

スタッフブログ

TECHNICAL

テクログ

2014.06.06

Objective-C | 非同期通信 メッセージ通知バージョン

テクログ

Mac,iPhone,Objective-C 全て利用歴6ヶ月の新米プログラマーが送る

自分が使って役立ったmethod&Tips集

元ネタはありますが単なるコピペを紹介してるわけではありません。

ちゃんと自前で作ってます。(謎のアピール)

実務で通信するなら、AFNetworking 2.0 使った方がいいです。

変な取り回しも無いし世界中で使われているので間違いありません。

その上でご覧ください

シリーズ第13弾です。

前回非同期通信簡単バージョンの改良です。

NSRunLoopで通信待機するため、待機中にイベントが発生すると拾ってしまうことがあります。

そのため連続した操作の途中で通信する場合には向いていません。

通信終了時に 内部でNSNotification を利用して終了通知を行い。それをトリガーとして以降の処理を実行します。

サーバープログラムは使い回しなので割愛

前回のソースを流用するので注意点も同じ

続いてiOS側。Xcodeでフォームに配置したボタンをAction接続してあります

NSURLConnectionDelegate も利用します

外部ライブラリでくるくる回る画像を利用してます。
https://github.com/samvermette/SVProgressHUD
をダウンロードして FinderからSVProgressHUDディレクトリを自分のプロジェクトにポイっと入れて下さい

ここから新しいところ。

「// loop やめる」で、検索して貰うと修正箇所がわかります

LOOP待機後に行っていた処理をやめて、NSNotificationに置き換え。

処理終了後にSVProgressHUDを解除すると画面が触れるようになります。

ViewController.h

#import 

@interface ViewController : UIViewController
- (IBAction)async:(id)sender;

@end

ViewController.m

#import "ViewController.h"
#import "SVProgressHUD.h"

@interface ViewController (){
    NSString       *connectStatus_;
    NSMutableData  *mData_;    // json
    NSMutableArray *cellList_;
}

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
?// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark svr connection
// 非同期通信でgroup 1record 取得
- (void)getJson
{
    // 通信中表示
    //[SVProgressHUD showWithStatus:@"ユーザー情報取得" maskType: SVProgressHUDMaskTypeBlack];
    [SVProgressHUD showWithMaskType: SVProgressHUDMaskTypeClear];
    connectStatus_ = @"start";
    
    NSString *query = [NSString stringWithFormat:@"input=%@", @"test-test"];
    NSData *queryData = [query dataUsingEncoding:NSUTF8StringEncoding];
    
    NSString *url = @"http://localhost/blogasync1.php";
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
    [request setTimeoutInterval:30]; //タイムアウトを30秒に設定
    [request setURL:[NSURL URLWithString:url]];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:queryData];
    
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    [NSURLConnection connectionWithRequest:request delegate:self];
    NSLog(@"async connection");
    
    // loop やめる
    //通知登録
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(FinishMethod) name:@"end" object:nil];
    //通信開始
    [NSURLConnection connectionWithRequest:request delegate:self];
    //NSLog(@"async connection-grpsch");
    // loop やめる

    /*
    while ([connectStatus_ isEqualToString:@"start"]) {
        // while 内で一旦 NSRunLoop へ制御戻してやる。runUntilDateはモードとしてNSDefaultRunLoopModeを用いる
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]]; //0.5sec
    }
    */
    /* 以降の処理を分割しないとすぐに処理が実行されてしまう
    if ([connectStatus_ isEqualToString: @"OK"]) {
        NSError *error = nil;
        //NSDictinaryがNSArrayになって返ってきます(id の中に入る)
        id json = [NSJSONSerialization JSONObjectWithData:mData_ options:NSJSONReadingAllowFragments error:&error];
        if(!error) {
            if (json == [NSNull null]) {
                return;
            }
            cellList_     = [NSMutableArray array];
            NSUInteger cnt = [json count];
            for (int idx=0; idx<cnt; idx++)="" {<br="">                [cellList_ addObject:json[idx][@"input"]];
                [cellList_ addObject:json[idx][@"ret"]];
            }
        }
    }
    // 通信中表示を消す
    [SVProgressHUD dismiss];
     */
}


//通信開始時に呼ばれる
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"receive response");
    
    mData_ = [NSMutableData data];
}

//通信中常に呼ばれる
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSError *jsonError;
    NSMutableArray *returnedData = [[NSMutableArray alloc] init];
    returnedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
    NSLog(@"%@", returnedData);
    
    //通信したデータを入れていきます
    [mData_ appendData:data];
}

//通信終了時に呼ばれる
- (void)connectionDidFinishLoading: (NSURLConnection *)connection
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    NSLog(@"finish connection");
    
    connectStatus_ = @"OK";
    // loop やめる
    // 通知を作成する
    NSNotification *n = [NSNotification notificationWithName:@"end" object:self];
    // 終了通知を実行して関数を呼ぶ
    [[NSNotificationCenter defaultCenter] postNotification:n];
    
    //    NSError *error = nil;
    //    //NSDictinaryがNSArrayになって返ってきます(id の中に入る)
    //    id json = [NSJSONSerialization JSONObjectWithData:self.mData options:NSJSONReadingAllowFragments error:&error];
    //    if(!error) {
    //        //NSLog(@"%@",json);
    //        connectStatus_ = @"OK";
    //    } else {
    //        NSLog(@"json error-1");
    //        connectStatus_ = @"NG";
    //    }
}

//通信エラー時に呼ばれる
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    //エラー処理を書く
    NSLog(@"err %@",[error localizedDescription]);
    // 通信中表示を消す
    [SVProgressHUD showErrorWithStatus:@"接続に失敗しました"];
    connectStatus_ = @"NG";
    
    // エラー情報を表示する。
    // objectForKeyで指定するKeyがポイント
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
    
    // loop やめる
    // 終わったら通知を消す
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"end" object:nil];
}
// loop やめる
//ループで待機させてたその後の処理を移動
- (void)FinishMethod {
    if ([connectStatus_ isEqualToString: @"OK"]) {
        NSError *error = nil;
        //NSDictinaryがNSArrayになって返ってきます(id の中に入る)
        id json = [NSJSONSerialization JSONObjectWithData:mData_ options:NSJSONReadingAllowFragments error:&error];
        if(!error) {
            if (json == [NSNull null]) {
                return;
            }
            cellList_     = [NSMutableArray array];
            NSUInteger cnt = [json count];
            for (int idx=0; idx<cnt; idx++)="" {<br="">                [cellList_ addObject:json[idx][@"input"]];
                [cellList_ addObject:json[idx][@"ret"]];
            }
        }
    }
    // 通信中表示を消す
    [SVProgressHUD dismiss];
}

- (IBAction)async:(id)sender
{
    [self getJson];
}
@end
</cnt;></cnt;>

そのほかのObjective-C関連の記事をお探しならコチラをどうぞ

弊社から出している拙作スケジュールのアプリです。
スケジュールというかちょっとした予定を入力して、社長、同僚、家族がどこ行った??っていうときに第三者が確認するためのアプリです
是非ダウンロードして感想をお聞かせ下さい。

『Team Scheduler』 概要
▼アプリ価格: 無料
▼対応OS: iOS(iPhone/iPod Touch)、Android
▼カテゴリ: 仕事効率化(App Store)、ビジネス(Google Play)
▼対応言語: 日本語
▼推奨環境:
iOS版: iPhone4以降、iOS6. 0以降
Android版: Android OS 2. 3以降
▼ダウンロード:
App Storeからダウンロード
Google playで手に入れよう

この記事を書いた人

core-corp

入社年

出身地

業務内容

特技・趣味

テクログに関する記事一覧

TOP