socket.io-ios简介
你可以使用socket.io通过swift编写在iOS和OS的客户端上. 同时保持简单表现良好的JavaScript客户端.
import Foundation
let socket = SocketIOClient(socketURL: "localhost:8880")
socket.on("important message") {data, ack in
println("Message for you! \(data?[0])")
ack?("I got your message, and I'll send my response")
socket.emit("response", "Hello!")
}
socket.connect()
xxoo -demo : 通过这个demo,展示如何使用它们在真实的项目中.
在本教程中,我们将创建一个小iOS程序,演示socket.io. 你可以通过观察这些代码学的更好;本教程重点不是解释iOS,所以你要有一定的XCode基础. 引入socket.io-client-swift
.
若要在OC中使用
从xcode中创建一个新项目, 取一个名字.我的命名可TicTacIOiOS
下一步是获取socket.o-client-swift代码,你可以使用git clone或者是下载一个发行版本. 之后将它添加到你的项目, 简单的拖动SocketRocket文件到新建组名’SwiftIO’中,确保选择的复制.
可以编译一下.
现在,假设你已经创建了你的UI界面, 是时候添加代码将于我们的socket.io接口服务器.
SocketIOClient类型
的成员socket
.let socket = SocketIOClient(socketURL:"localhost:8900")
self.addHandlers()
self.socket.connect()
func addHandlers(){
// our socket handlers go here
}
因为我们要添加处理程序,我认为值得一提的是swift语法的闭包形式.
我不会告你你们示例程序的所有细节, 只说明你需要知道的几个重要的事,当你使用socket.io-client-swift时.
// 使用闭包的速记参数.
self.socket.onAny {println("Got event: \($0.event), with items: \($0.items)")}
self.socket.on("startGame") {[weak self] data, ack in
self?.handleStart()
return
}
现在来解释一些事: [weak self]防循环引用.当socket对象超出范围时,保证回收.第一个参数: 回调可选的NSArray类型,它将包含所有接收到的数据和事件或是nil. 第二个参数 回调可选的AckEmitter类型, 这只是补充参数, 后面会用到.
self.socket.on("win") {[weak self] data, ack in
if let name = data?[0] as? String, typeDict = data?[1] as? NSDictionary { self?.handleWin(name, type: typeDict) }
}
如上所述, 要注意的是,几乎所有的数据处理程序, 你会做一些可选的展开, 这是一个使用JavaScript的不幸产物.
self.socket.on("gameReset") {data, ack in
ack?(false)
}
在这个简化的例子中, 我们只需要向服务器发送一个请求, 我们不再玩了,记住AckEmitter有一个可变的定义,所以你想要可以一次发送多个事件.
接下来你可能想知道是如何从客户端发送事件的, 其实和socket.io-client几乎一样.
在我们的ViewController中,我们有一个方法来处理 当用户想动的时候, 我们将展示如何向服务器发送数据,先不论逻辑.
@IBAction func btnClicked(btn:UIButton) {
let coord:(x:Int, y:Int)
//决定coord
self.socket.emit("playerMove", coord.x, coord.y)
}
这是你所有要发送的数据. 一些其他的发送例子demo不演示.
如前所述,JSON在swift是最好的字典,值得庆幸的是,你不需要把它转换其他的格式为了通过socket.io .
let myJSON = [
"name": "bob"
]
socket.emit("jsonTest", myJSON)
二级制数据也可,你也无需担心.
let data = "Hello, ".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
let data2 = "World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
socket.emit("dataTest", data, ["world": data2])
客户端还可以请求发送事件的ACK, 这是通过使用emitWithAck
方法返回的对象. 你可以添加一个这个handler.
socket.emitWithAck("needsAck", "test").onAck {data in
println("got ack with data: (data)")
}
iOS非常限制后台, 因此,不要指望你的socket连接在后台不会断开. 所以最好创建一个任务.进入后台时主动关闭连接. 需要时再重新连接.
github.
let socket = SocketIOClient(socketURL: NSURL(string: "http://localhost:8080")!, options: [.Log(true), .ForcePolling(true)])
socket.on("connect") {data, ack in
print("socket connected")
} //开始
socket.on("currentAmount") {data, ack in
if let cur = data[0] as? Double {
socket.emitWithAck("canUpdate", cur)(timeoutAfter: 0) {data in
socket.emit("update", ["amount": cur + 2.50])
}
ack.with("Got your currentAmount", "dude")
}
}
socket.connect()
NSURL* url = [[NSURL alloc] initWithString:@"http://localhost:8080"];
SocketIOClient* socket = [[SocketIOClient alloc] initWithSocketURL:url options:@{@"log": @YES, @"forcePolling": @YES}];
[socket on:@"connect" callback:^(NSArray* data, SocketAckEmitter* ack) {
NSLog(@"socket connected");
}];
[socket on:@"currentAmount" callback:^(NSArray* data, SocketAckEmitter* ack) {
double cur = [[data objectAtIndex:0] floatValue];
[socket emitWithAck:@"canUpdate" withItems:@[@(cur)]](0, ^(NSArray* data) {
[socket emit:@"update" withItems:@[@{@"amount": @(cur + 2.50)}]];
});
[ack with:@[@"Got your currentAmount, ", @"dude"]];
}];
[socket connect];
直接拖入项目即可,确保是复制选项.
import PackageDescription
let package = Package(
name: "YourSocketIOProject",
dependencies: [
.Package(url: "https://github.com/socketio/socket.io-client-swift", majorVersion: 5)
]
)
这时import SocketIOClientSwift
添加这行命令到Cartfile
:
github "socketio/socket.io-client-swift" ~> 6.0.0 # Or latest version
运行 carthage update --platform iOS,machos
Pod file文件中添加 pod 'Socket.IO-Client-Swift'
init(var socketURL: NSURL, options: Set<SocketIOClientOption> = [])
创建一个新的SocketIOClient. 参数option是 SocketIOClientOption的设置.如果你的socket.io服务器是要安全的,你需要指定https
在你的socketURL参数中.
convenience init(socketURL: NSURL, options: NSDictionary?)
同上, 但是为了ObjC准备,使用字典.
所有关于SocketIOClientOption的设置.如果是ObjC,转换名字lowerCamelCase.
case ConnectParams([String: AnyObject]) // 通过字典内容连接
case Cookies([NSHTTPCookie]) // An array of NSHTTPCookies. Passed during the handshake. Default is nil.
case DoubleEncodeUTF8(Bool) // Whether or not to double encode utf8. If using the node based server this should be true. Default is true.
case ExtraHeaders([String: String]) // 添加自定义请求头初始化来请求, 默认为nil
case ForcePolling(Bool) // 是否使用 xhr-polling. Default is `false`
case ForceNew(Bool) // 将为每个连接创建一个新的connect, 如果你在重新连接时有bug时使用.
case ForceWebsockets(Bool) // 是否使用 WebSockets. Default is `false`
case HandleQueue(dispatch_queue_t) // 调度handle的运行队列. Default is the main queue.
case Log(Bool) // 是否打印调试信息. Default is false.
case Logger(SocketLogger) // 可自定义SocketLogger调试日志.默认是系统的.
case Nsp(String) // 如果使用命名空间连接. Must begin with /. Default is `/`
case Path(String) // 如果服务器使用一个自定义路径. 例如: `"/swift/"`. Default is `""`
case Reconnects(Bool) // 是否重新连接服务器失败. Default is `true`
case ReconnectAttempts(Int) // 重新连接多少次. Default is `-1` (无限次)
case ReconnectWait(Int) // 等待重连时间. Default is `10`
case SessionDelegate(NSURLSessionDelegate) // NSURLSessionDelegate 底层引擎设置. 如果你需要处理自签名证书. Default is nil.
case Secure(Bool) // 如果连接要使用TLS. Default is false.
case SelfSigned(Bool) // WebSocket.selfSignedSSL设置 (Don't do this, iOS will yell at you)
case VoipEnabled(Bool) // 如果你的客户端使用VoIP服务,只有用这个选项,Default is false
on(event: String, callback: NormalCallback) -> NSUUID // 给一个事件添加一个句柄. Items are passed by an array. 可以发送ack请求. 例如,返回一个唯一ID.
once(event: String, callback: NormalCallback) -> NSUUID // 同上,但只执行一次.
onAny(callback:((event: String, items: AnyObject?)) -> Void) //可以给所有事件添加一个句柄. event可以接收任何事件. emit(event: String, _ items: AnyObject...) // 发送一个或多条消息. emit(event: String, withItems items: [AnyObject]) // emit for Objective-C emitWithAck(event: String, _ items: AnyObject...) -> (timeoutAfter: UInt64, callback: (NSArray?) -> Void) -> Void // 给服务器发送一个ack确认请求. 返回一个函数,你可以用它添加一个句柄. 注意: 直到你调用这个返回函数,才会发送消息
emitWithAck(event: String, withItems items: [AnyObject]) -> (UInt64, (NSArray?) -> Void) -> Void // 同上,为Objective-C准备的
connect() // 建立一个连接到服务器. 连接成功会触发 "connect"事件
connect(timeoutAfter timeoutAfter: Int, withTimeoutHandler handler: (() -> Void)?) // 连接到服务器. 如果连接超时,会调用handle disconnect() // Closes the socket. 重开一个断开连接的socket还没完全测试. reconnect() // Causes the client to reconnect to the server. joinNamespace(namespace: String) - Causes the client to join namespace. 不应该被调用,除非你手动改变命名空间. leaveNamespace() // Causes the client to leave the nsp and go back to '/' off(event: String) - Removes all event handlers for event. off(id id: NSUUID) - Removes the event that corresponds to id. removeAllHandlers() - Removes all handlers.