Blog

ブログ

iosでsocket.ioを試してみた

2015.11.30 公開

socket.ioで投稿した内容がリアルタイムに表示される簡単なサンプルを作ってみました。


サーバーサイドの実装

サーバーサイドは node.jsです。

ローカルの適当な場所に作業用のフォルダを作成します。

$ mkdir socket-saver && cd socket-server/

socket.ioを追加します。

$ npm install socket.io

server.jsというファイルを作りサーバーの実装を記述します。

var http = require("http");
var server = http.createServer(function(req,res) {
    res.write("Hello World!!");
    res.end();
});

var io = require('socket.io')(server);

var postArray = [];

// クライアント接続時
io.on('connection', function(socket) {
    console.log("client connected!!")

    // クライアント切断時
    socket.on('disconnect', function() {
        console.log("client disconnected!!")
    });

    // クライアント投稿時
    socket.on("post", function(obj){
        postArray.push(obj);
        // クライアントに最新のデータを送る
        io.emit("addedPost", JSON.stringify(postArray));
    });
});

server.listen(8080);

“post”という名前で投稿内容を取得し”addedPost”でクライアントに最新のデータを送っています。

サーバーの実装はこれで終わりです。


ios実装

プロジェクトを作成しswift用のsocket.ioのライブラリーをcocoapodsで追加します。

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

pod 'Socket.IO-Client-Swift', '~> 4.1.2' # Or latest version

これで$pod install とするとsocket.ioがインストールされます。

画面のレイアウトです。

socket-io-1

投稿ボタン、テキストフィールド2つ、投稿された内容が表示されるテーブルビューを配置します。

socket.ioの実装です。

socket = SocketIOClient(socketURL: SocketURL, options: nil)

// 接続時
socket.on("connect") { data in
    print("socket connected!!")
}

// 切断時
socket.on("disconnect") { data in
    print("socket disconnected!!")
}

// 投稿された時
socket.on("addedPost") { (data, emitter) in
    if let message = data as? [String] {
        // 最新のデータを取得
        print(message[0])
        let jsonData: NSData = message[0].dataUsingEncoding(NSUTF8StringEncoding)!
        var err:NSError?
        do {
            self.postArray = try NSJSONSerialization.JSONObjectWithData(
                jsonData, options:[]) as? NSMutableArray
        } catch let error as NSError {
            err = error
            self.postArray = nil
        }
        print(err)

        // テーブル更新
        self.tableView.reloadData()
    }
}

// 接続開始
socket.connect()

// 投稿
@IBAction func pushPostButton(sender: AnyObject) {
    let post : Dictionary<String, String> =
 [ "name":self.nameTextField.text!, "text":self.postTextField.text!]
    self.socket.emit("post", post);
}

ボタンが押された時に”post”という名前で投稿内容をサーバーに送ります。

サーバーに投稿の内容が送られると”addedPost”という名前でサーバーから最新のデータが送られてくるのでデータ取得しテーブルのデータを更新します。

全体のコードはこんな感じです。

//
//  ViewController.swift
//

import UIKit
import Socket_IO_Client_Swift

class ViewController: UIViewController {
    let SocketURL = "http://localhost:8080/"
    
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var postTextField: UITextField!
    @IBOutlet weak var tableView: UITableView!
    var socket: SocketIOClient!
    var postArray: NSMutableArray!
    
    // MARK: - LifeCycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        postArray = NSMutableArray()
        
        socket = SocketIOClient(socketURL: SocketURL, options: nil)
        socket.on("connect") { data in
            print("socket connected!!")
        }
        socket.on("disconnect") { data in
            print("socket disconnected!!")
        }
        
        socket.on("addedPost") { (data, emitter) in
            if let message = data as? [String] {
                print(message[0])
                let jsonData: NSData = message[0].dataUsingEncoding(NSUTF8StringEncoding)!
                var err:NSError?
                do {
                    self.postArray = try NSJSONSerialization.JSONObjectWithData(
                        jsonData, options:[]) as? NSMutableArray
                } catch let error as NSError {
                    err = error
                    self.postArray = nil
                }
                print(err)
                self.tableView.reloadData()
            }
        }
        socket.connect()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Action
    
    @IBAction func pushPostButton(sender: AnyObject) {
        let post : Dictionary<String, String> = [ "name":self.nameTextField.text!, "text":self.postTextField.text!]
        self.socket.emit("post", post);
    }
    
    // MARK: - TableView

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.postArray.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
        cell.backgroundColor = UIColor.clearColor()
        
        let data : Dictionary<String, String> = self.postArray.objectAtIndex(indexPath.row) as! Dictionary<String, String>
        print(data)
        
        cell.textLabel?.text = data["text"]
        cell.textLabel?.font = UIFont.boldSystemFontOfSize(17.0)
        cell.detailTextLabel?.text = data["name"]
        return cell
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 80
    }
}

デモ

$node server.js でサーバーを起動しアプリを動かしてみます。

socket

できました!!

簡単な実装ですがiOSアプリからnode.js+Socket.IO間で双方向通信が実現できました。

今度はもっと複雑な処理に挑戦してみようと思います。


参考URL

socket.io

socket-io-on-ios