NSURLSessionを使ってJSONデータの取得(iOS, Objective-C)

NSURLSession関連のポストが増えてきましたね.いい感じです. 今回はNSURLSessionを使ってJSONデータを取得してみます.格納はまた後日. ここまで行けば格納は問題ないと思います.
JSONデータはここ から取得します. JSON Generator – tool for generating random JSON data を使えば簡単にテストJSONデータが作成できるみたいです. ソースコードは以下のようになりました.

NSString *urlString = @"http://www.json-generator.com/j/bYArmwnBQi?indent=4";
NSURL *url = [NSURL URLWithString:urlString];

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil  ];

NSURLSessionDataTask *jsonData = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (!error) {
        NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *) response;
        if (httpResp.statusCode == 200) {
            NSError *jsonError;

            NSArray *testJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];
            if (!jsonError) {
                // something for json data
                dispatch_async(dispatch_get_main_queue(), ^{
                    // something after parsing json data
                });
            }
        }
    }
}];
[jsonData resume];

somethingの所に格納処理を書けば良いかと思います. testJSONの型をNArrayにしていますが,ここは扱うJSONによって適宜変更で. とりあえずこれでやっかいな所は終わりそうだ.次は格納も含めてGoogle Image Search APIを使ってみたいと思います. あくまでも予定.

広告

URLから画像をダウンロードして表示(iOS, Objective-C, NSURLSession)

前回,URLから画像を取得し表示 をやりましたが,今回はURLから画像をダウンロードして表示します. これには,NSURLSessionを使います. NSURLSessionについては NSURLSession Tutorial で学べます. 僕もまだ詳しいことはわかっていないのですが,こんな流れだそうです.

  1. NSURLSessionConfigurationを作る(config)。
  2. configからNSURLSessionを作る(session)。
  3. sessionからTaskを作る(task)。
  4. タスク(task)をスタート。

コードはこんな感じになりました.imageViewというUIImageViewを定義していると仮定します.

NSString *urlString = @"http://images.moneysavingexpert.com/images/OrangeLogo.jpg";
NSURL *url = [NSURL URLWithString:urlString];

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];

NSURLSessionDownloadTask *getImageTask = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
    UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
    dispatch_async(dispatch_get_main_queue(), ^{
        _imageView.image = downloadedImage;
    });
}];
[getImageTask resume];

今回は画像のダウンロードということで,タスクにdownloadTaskWithURLを使っています. ということはいろいろなタスクが用意されている,ということになりそうですね. そして完了したらcompletionHandlerで定義した関数が実行されます. これらは非同期処理なので,resumeをお忘れなく.

ちなみに以下のようにも書けるみたいだ.
ヘッダーファイル(別にViewControllerでなくても良い)

@interface ViewController : UIViewController <NSURLSessionDownloadDelegate>

実装ファイル

NSString *urlString = @"http://images.moneysavingexpert.com/images/OrangeLogo.jpg";
NSURL *url = [NSURL URLWithString:urlString];

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil  ];

NSURLSessionDownloadTask *getImageTask = [session downloadTaskWithURL:url];
[getImageTask resume];

最後に以下のメソッドを実装ファイルに追加する.

-(void)URLSession😦NSURLSession *)session downloadTask😦NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL😦NSURL *)location {
    UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
    dispatch_async(dispatch_get_main_queue(), ^{
        _imageView.image = downloadedImage;
    });
}

NSURLSessionでGoogleImageSearchAPIを使う(iOS, Objective-C)

自分用備忘録です. NSURLSessionを使ってJSONを取得する方法をやったので,今回はGoogle Image Search APIをObjective-Cで使ってみたいと思います. このAPIをJavascript, Pythonで触ったことがあるのでAPIについては割愛. 今回の目標はあるクエリ(orangeとした)で検索して1ページ目全8件の画像を取得し,それぞれのURLを,

@property (nonatomic, strong) NSMutableArray *imageURLs;

こいつに格納する.その後格納された件数を出力する,というものです.あまり楽しくはないか. 前回のポストとほとんど同じで,このAPI用に何か特別な処理をする,ということはない. コードはこんな感じ.

NSString *keyword = @"orange";

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSString *urlBaseString = @"http://ajax.googleapis.com/ajax/services/search/images?v=1.0&hl=ja&rsz=large&start=0&q=%@";
NSString *urlString = [NSString stringWithFormat:urlBaseString, keyword];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil  ];

NSURLSessionDataTask *jsonData = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    if (!error) {
        NSHTTPURLResponse *httpResp = (NSHTTPURLResponse *) response;
        if (httpResp.statusCode == 200) {
            NSLog(@"success!");
            NSError *jsonError;

            NSDictionary *rawJSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonError];

            NSMutableArray *imageURLsFound = [[NSMutableArray alloc]init];

            if (!jsonError) {
                NSArray *results = rawJSON[@"responseData"][@"results"];
                for (NSDictionary *result in results) {
                    NSURL *imageURL = [NSURL URLWithString:result[@"url"]];
                    [imageURLsFound addObject:imageURL];
                }
                self.imageURLs = imageURLsFound;

                dispatch_async(dispatch_get_main_queue(), ^{
                    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                    NSLog(@"%lu", _imageURLs.count);
                });
            }
        }
    }
}];
[jsonData resume];

個人的に気になるのは以下の二つ.まずこれ.

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

これをYES, NOで切り替えてるのだけどもなんなんだろうこれは. 名前的に上のネットワーク使用中の出すか出さないかだと思うんだが,と思ったらその通りだった. 気になる方は是非消して実行してみてほしい.
次にこれ.

dispatch_async(dispatch_get_main_queue(), ^{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    NSLog(@"%lu", _imageURLs.count);
});

dispatch_asyncで非同期処理の終わりを意味するのでしょうか. とりあえず書いておいて,JSON解析後の処理をここに書くのがよろしいのではないでしょうか. そんな感じ.全くわかってないけど,一歩一歩ってやつだよね.

URLから画像を取得し表示(iOS,Objective-C)

自分のための備忘録ポスト. URLから画像を取得し表示まで行います. imageViewという名前でUIImageViewを追加していることを仮定します.

NSString *urlString = @"http://images.moneysavingexpert.com/images/OrangeLogo.jpg";
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc]initWithData:data];
[self.imageView setImage:img];

これで完了.素晴らしい.次はNSURLSessionを使ってURL→ファイル→UIImageをやりたいと思います(合ってるかな?).

Basic Summarization Modelで文書要約 Python

Introduction

必要に迫られて文書要約をやることになりました.
自然言語処理には1年携わっていましたが素人同然です,どうしましょう.
とりあえず文書要約とGoogleで調べて,
「へぇDocument Summarizationっていうんだ」ということを知りました.
まぁ当然次はツールを探すわけですが,うーんいいのないなあ.
でも論文はあるはずだ,ということでNIPSへ.ああ,お門違いだった.
ということでACL Anthologyを除きにいきました.
そこで見つけたのがMulti-document Summarizationという言葉.
N個の文書をまとめて一つの要約を作る,のがMultiだそうです.
ああ,僕は違うや,
ということで僕が探しているのは普通のDocument Summarizationの論文なんだということを知りました.
そして見つけました,良さそうな論文.今日はツイている予感.

よく使われるのは文の位置らしい.でもここでは単語の位置を使うんです!とおっしゃっていました.
機械学習の論文は全く頭が付いて行かないので,久しぶりに言っていることが割とわかる内容で,僕はうれしかったです.

Basic Summarization Model (Theory)

この論文の3章にBasic Summarization Modelというのが紹介されていました.ここからが本題です.前置き,長いですね.とりあえず初心者だからこの基礎っぽいものを習得しようと思い読んだら割とストレートな感じでした.素晴らしい.理論はこんな感じです.画像2枚.

Implement

さてここからコードを書いてみました.
いつもクラスを定義しようか迷うのですが,だいたい関数で事足りるんですよね.
僕みたいな小規模なことしかやらない場合はクラスをめったにかかない.
コードはこんな感じです.summarizeというのがそれです.

特にめぼしいことはしていません.あ,僕は日本人なのでとりあえず日本語を対象にしています.
まず文書を文に区切ります.MeCabを使ってますが,単に”.”が来たら区切るというだけのことをしています.
次にfreqを算出するためにfreqdictというのを作ってます.おなじみの処理ですね.
ちなみにnltk.FreqDistという素晴らしいものがあるのですが,
なぜか処理が重かったので自分で書きました.
次にscoreですね.そのままです.
そしてここ,文をscoreでランキングして上位からとっていくところ.ここかっこよくないですか?
あるリストをソートしてそのインデックスを得るにはどうしたら良いか調べたらここにクールなコードが.

というわけでそれを使っています.今回は降順なのでreverse=True.
あとは普通です.そんな感じです.眠いですね.

Experiment

実験してみました.いやあ,実験は楽しい.
ターゲットは僕の大好きなサイト,Lifehacker.jp様の記事です.

これを要約してみます.ちなみにタイトルは要約対象から外してます.
ちなみに生だとこんな感じです.

真に「使える」手書きメモアプリだと思わせてくれた『DioNote』
====================================================================================================
Android:手書きメモアプリが使えないのは過去の話になったかも。
「手書きメモアプリ」と聞くだけで、筆者は敬遠するところがありました。
今までいくつかのアプリを試してきて、うまく文字が書けたり、正しく反映されたためしがなかったのです。
大人しくキーボードから入力するメモが一番だ、と。
ですが、今回紹介する『DioNote』は、手書き反映の機敏さといい、認識力の高さといい、
かなりの実力を持っていて、久々に「いいね!」と言いたくなるアプリでした。
加えて、画像の挿入や文字入力、メモのショートカットをホームに置けるなど、
細かな機能も実装されており、あらゆる点からなかなか使える仕上がりとなっています。
早速、トップ画面右上のプラスマークからメモを作ってみます。
ノートのようなデザインです。画面下部の領域に文字を手書きで入力していきます。
一文字書いてみると、反応の正確さにビックリします。
すぐさま一文字書いたことが認識され、新たな文字、さらに新たな文字...と、そのテンポの良さも素晴らしい。
ちなみに、一文字ずつだけでなく、横に連続で書いていくことも可能です。
画面右上のメニューから「キャンパス作成」をタップすると、真っさらな自由帳のような画面になります。
ここでは画像の貼り付けも自由にでき、より気ままなメモを作成できます。

Result

Basic Summarization Modelによる実験結果は以下のようになりました.
タイトルと一緒に出せばいい感じじゃないですか?

真に「使える」手書きメモアプリだと思わせてくれた『DioNote』
====================================================================================================
大人しくキーボードから入力するメモが一番だ、と。
ノートのようなデザインです。
画面下部の領域に文字を手書きで入力していきます。
一文字書いてみると、反応の正確さにビックリします。
すぐさま一文字書いたことが認識され、新たな文字、さらに新たな文字...と、そのテンポの良さも素晴らしい。

Summary

Basic Summarization Modelで僕の文書要約の旅を出発することができた.
基礎的ながらなかなかの威力が証明された.
引き続き上の論文を読み,理解を深めたいと思う.

keyartというwebアプリを公開しました

keyart

enter image description here

keyartというwebアプリを公開しました.
http://nktyasu.dip.jp/keyart
からアクセスできます.
画像を検索して1枚の画像を作成できます.基本に検索して気に入った画像ができるまでRedrawをクリックし続ければよいと思います.画像ができたらDoneをクリックします.右側に完成した画像が出てくるので右クリックで保存できます.

是非遊んでみてください.感想は@nkt_devまたはコメントまで.

ajaxでjsonを取得しグローバル変数へ格納(javascript ajax jquery)

ajaxでjsonを取得しグローバル変数へ格納する方法のメモです.

$(function(){
    var results;
    $.ajax({
        type: "GET",
        url: url,
        data: data,
        dataType: "json",
        timeout: 120000,
        error: errorHandlier,
        success: function(r){
            results = r.data;
        }
    });
    setTimeout(function(){
        if(results != null){
            /* whatever you want to do using the results */
        }
        else{
            setTimeout(arguments.callee, 100);
        }
    }
});

同期通信を用いた方法も紹介されていました.

var hoge
    function setPreference(){
        $.ajaxSetup({async: false});//同期通信(json取ってくるまで待つ)
        $.getJSON("preference.json", function(data){
            hoge = data.param;
        });
        $.ajaxSetup({async: true});
    }

しかし,setTimeoutを使う方が安定しているように感じます.