umegusa's blog

備忘録

SwiftでNSURLConnectionを使ってHTMLを取得

Swift使ってHTML取得してみました。
Objective-Cに比べてすげー楽にすらすら書ける気がする。。。

NSURLConnectionを使用して非同期通信

NSURLConnectionに用意されているプロトコルを使って実装します。

    // サーバからレスポンスを受け取ったときのデリゲート
    func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
    }
    
    // サーバからデータが送られてきたときのデリゲート
    func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
    }
    
    // データロードが完了したときのデリゲート
    func connectionDidFinishLoading(connection: NSURLConnection!){
    }

これらのメソッドを実装するだけです。
Objective-Cとなんら変わらない。

ソースコードの全貌

ということで今回書いたコードは以下のとおり。
単純にURL指定してURLをコンソールに出力。
画面にはsuccessと表示するだけです。

ViewController.swift

import UIKit


class ViewController: UIViewController, ConnectionResult {
    // プロトコルを継承する
    
    // !マークは値が必ず入っていることが保証されるOptional型
    // 値が入っていないとエラーになる
    // この場合はStroyboardからひもづけているので必ずついていなければならない
    // reference outlet@storyboard
    @IBOutlet var label: UILabel!
    var connection : Connection!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // touch up inside@storyboard
    @IBAction func btnClick(sender: AnyObject) {
        // インスタンス化とデリゲートのセット
        connection = Connection(urlStr: "ここにURL")
        connection.delegate = self
        connection.doConnect()
    }
    
    // delegate
    // 実際に処理を行う
    func showResult(resultMessage: String?) -> Void {
        label.text = resultMessage
    }
}

Connection.swift

import Foundation

// プロトコル
protocol ConnectionResult{
    func showResult(resultMessage: String?) -> Void
}

public class Connection : NSObject{
    
    // 参考: 
    // NSURLConnection ttp://stackoverflow.com/questions/24176362/ios-swift-and-nsurlconnection
    // Delegate, Protocol ttp://qiita.com/mochizukikotaro/items/a5bc60d92aa2d6fe52ca
    
    // nilが入ってるなんてあり得ない!
    var urlStr : String
    var data : NSMutableData? = nil
    var delegate : ConnectionResult!
    
    // コンストラクタ
    public init(urlStr: String) {
        self.data = NSMutableData()
        self.urlStr = urlStr
    }
    
    // アクセス
    public func doConnect() -> Void{
        var url : NSURL = NSURL(string: urlStr)
        // キャッシュを無視
        var request : NSURLRequest = NSURLRequest(URL: url, cachePolicy:NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData, timeoutInterval: 60.0)
        
        var connect : NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: true)
        // 接続開始
        connect.start()
    }
    
    // サーバからレスポンスを受け取ったときのデリゲート
    func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) {
        // Recieved a new request, clear out the data object
        self.data! = NSMutableData()
    }
    
    // サーバからデータが送られてきたときのデリゲート
    func connection(connection: NSURLConnection!, didReceiveData data: NSData!){
        self.data!.appendData(data)
    }
    
    // データロードが完了したときのデリゲート
    func connectionDidFinishLoading(connection: NSURLConnection!){
        // バイナリデータが発行される
        let html : String = NSString(data: self.data!, encoding: NSUTF8StringEncoding)
        // コンソールに出力
        println(html)
        
        // 処理を呼び出すだけ
        self.delegate.showResult("success!")
    }
}

DelegateとProtocolとを独自に実装。
これらについても忘れそうなのでそのうち残しておこう。
アクセス修飾子についての理解も甘い、CocoaとかFoundationとかは全publicじゃないとだめなのかな?
デリゲートメソッドprivateで定義したらだめだった。

githubにもあげました。
https://github.com/kaisou4537/swiftstudy/tree/master/swift_4/ConnectionTest

Swift面白い

全文英語だけど何とか読めるドキュメント。
まだiOSアプリ開発事態に慣れないので本読みながらサンプルアプリガッつりつくっていこう。

とはいってもモダンなプログラミング言語と言うだけあって「こう書けば動きそう」って書いたら割と動いちゃったりする。

やっていて楽しいのは久しぶりな感じ。
まだ新しいと言うのもあるけれども。。。