#2. Add support for messages that have multiple items. Add support for sending messages with multiple messages
This commit is contained in:
parent
2298cb2a1a
commit
a5db559bed
@ -26,9 +26,9 @@ import Foundation
|
||||
|
||||
class Event {
|
||||
var args:AnyObject!
|
||||
var currentPlace = 0
|
||||
var event:String!
|
||||
lazy var currentPlace = 0
|
||||
lazy var datas = [NSData]()
|
||||
var event:String!
|
||||
var placeholders:Int!
|
||||
|
||||
init(event:String, args:AnyObject?, placeholders:Int = 0) {
|
||||
@ -61,48 +61,42 @@ class Event {
|
||||
}
|
||||
}
|
||||
|
||||
func createMessage() -> String {
|
||||
var array = "42["
|
||||
array += "\"" + event + "\""
|
||||
|
||||
if args? != nil {
|
||||
if args is NSDictionary {
|
||||
array += ","
|
||||
var jsonSendError:NSError?
|
||||
var jsonSend = NSJSONSerialization.dataWithJSONObject(args as NSDictionary,
|
||||
options: NSJSONWritingOptions(0), error: &jsonSendError)
|
||||
var jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding)
|
||||
return array + jsonString! + "]"
|
||||
class func createMessageForEvent(event:String, withArgs args:[AnyObject],
|
||||
hasBinary:Bool, withDatas datas:Int = 0) -> String {
|
||||
|
||||
var message:String
|
||||
var jsonSendError:NSError?
|
||||
|
||||
if !hasBinary {
|
||||
message = "42[\"\(event)\""
|
||||
} else {
|
||||
array += ",\"\(args!)\""
|
||||
return array + "]"
|
||||
message = "45\(datas)-[\"\(event)\""
|
||||
}
|
||||
} else {
|
||||
return array + "]"
|
||||
}
|
||||
|
||||
for arg in args {
|
||||
message += ","
|
||||
|
||||
if arg is NSDictionary || arg is [AnyObject] {
|
||||
let jsonSend = NSJSONSerialization.dataWithJSONObject(arg,
|
||||
options: NSJSONWritingOptions(0), error: &jsonSendError)
|
||||
let jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding)
|
||||
|
||||
message += jsonString!
|
||||
continue
|
||||
}
|
||||
|
||||
if arg is String {
|
||||
message += "\"\(arg)\""
|
||||
continue
|
||||
}
|
||||
|
||||
message += "\(arg)"
|
||||
}
|
||||
|
||||
return message + "]"
|
||||
}
|
||||
|
||||
func createBinaryMessage() -> String {
|
||||
var array = "45\(self.placeholders)-["
|
||||
array += "\"" + event + "\""
|
||||
if args? != nil {
|
||||
if args is NSDictionary {
|
||||
array += ","
|
||||
var jsonSendError:NSError?
|
||||
var jsonSend = NSJSONSerialization.dataWithJSONObject(args as NSDictionary,
|
||||
options: NSJSONWritingOptions(0), error: &jsonSendError)
|
||||
var jsonString = NSString(data: jsonSend!, encoding: NSUTF8StringEncoding)
|
||||
return array + jsonString! + "]"
|
||||
} else {
|
||||
array += ",\"\(args!)\""
|
||||
return array + "]"
|
||||
}
|
||||
} else {
|
||||
return array + "]"
|
||||
}
|
||||
}
|
||||
|
||||
func fillInPlaceholders(args:AnyObject) -> AnyObject {
|
||||
func fillInPlaceholders(_ args:AnyObject = true) -> AnyObject {
|
||||
if let dict = args as? NSDictionary {
|
||||
var newDict = [String: AnyObject]()
|
||||
|
||||
@ -124,6 +118,27 @@ class Event {
|
||||
if string == "~~\(self.currentPlace)" {
|
||||
return self.datas.removeAtIndex(0)
|
||||
}
|
||||
} else if args is Bool {
|
||||
var returnArr = [AnyObject]()
|
||||
// We have multiple items
|
||||
// Do it live
|
||||
let argsAsArray = "[\(self.args)]"
|
||||
if let parsedArr = SocketIOClient.parseData(argsAsArray) as? NSArray {
|
||||
for item in parsedArr {
|
||||
if let strItem = item as? String {
|
||||
if strItem == "~~\(self.currentPlace)" {
|
||||
returnArr.append(self.datas[self.currentPlace])
|
||||
self.currentPlace++
|
||||
continue
|
||||
} else {
|
||||
returnArr.append(strItem)
|
||||
}
|
||||
} else {
|
||||
returnArr.append(item)
|
||||
}
|
||||
}
|
||||
return returnArr
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
@ -22,17 +22,21 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
|
||||
class EventHandler: NSObject {
|
||||
class EventHandler {
|
||||
let event:String!
|
||||
let callback:((data:AnyObject?) -> Void)!
|
||||
var callbackMult:((data:[AnyObject]) -> Void)!
|
||||
|
||||
init(event:String, callback:((data:AnyObject?) -> Void)?) {
|
||||
init(event:String, callback:((data:AnyObject?) -> Void)) {
|
||||
self.event = event
|
||||
self.callback = callback
|
||||
}
|
||||
|
||||
init(event:String, callback:((data:[AnyObject]) -> Void)) {
|
||||
self.event = event
|
||||
self.callbackMult = callback
|
||||
}
|
||||
|
||||
func executeCallback(args:AnyObject?) {
|
||||
if args != nil {
|
||||
callback(data: args!)
|
||||
@ -40,4 +44,8 @@ class EventHandler: NSObject {
|
||||
callback(data: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func executeCallback(args:[AnyObject]) {
|
||||
callbackMult(data: args)
|
||||
}
|
||||
}
|
||||
@ -26,13 +26,13 @@ import Foundation
|
||||
|
||||
class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
let socketURL:String!
|
||||
let secure:Bool!
|
||||
private let secure:Bool!
|
||||
private var handlers = [EventHandler]()
|
||||
private var lastSocketMessage:Event?
|
||||
private var pingTimer:NSTimer!
|
||||
var connected = false
|
||||
var connecting = false
|
||||
var io:SRWebSocket?
|
||||
var pingTimer:NSTimer!
|
||||
var reconnnects = true
|
||||
var reconnecting = false
|
||||
var reconnectAttempts = -1
|
||||
@ -110,14 +110,13 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
}
|
||||
|
||||
var frame:Event!
|
||||
var str:String!
|
||||
var str:String
|
||||
|
||||
if let dict = args as? NSDictionary {
|
||||
// Check for binary data
|
||||
let (newDict, hadBinary, binaryDatas) = self.parseNSDictionary(dict: dict)
|
||||
let (newDict, hadBinary, binaryDatas) = self.parseNSDictionary(dict)
|
||||
if hadBinary {
|
||||
frame = Event(event: event, args: newDict, placeholders: binaryDatas!.count)
|
||||
str = frame.createBinaryMessage()
|
||||
str = Event.createMessageForEvent(event, withArgs: [newDict], hasBinary: true, withDatas: binaryDatas!.count)
|
||||
self.io?.send(str)
|
||||
|
||||
for data in binaryDatas! {
|
||||
@ -129,51 +128,169 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
}
|
||||
} else if let binaryData = args as? NSData {
|
||||
// args is just binary
|
||||
frame = Event(event: event, args: ["_placeholder": true, "num": 0], placeholders: 1)
|
||||
str = frame.createBinaryMessage()
|
||||
str = Event.createMessageForEvent(event, withArgs: [["_placeholder": true, "num": 0]],
|
||||
hasBinary: true, withDatas: 1)
|
||||
|
||||
self.io?.send(str)
|
||||
let sendData = self.createBinaryDataForSend(binaryData)
|
||||
self.io?.send(sendData)
|
||||
|
||||
return
|
||||
} else if let arr = args as? NSArray {
|
||||
var hadBinary = false
|
||||
var placeholders = [AnyObject](count: arr.count, repeatedValue: 1)
|
||||
var datas = [NSData]()
|
||||
var placeNum = 0
|
||||
|
||||
for i in 0..<arr.count {
|
||||
if arr[i] is NSData {
|
||||
hadBinary = true
|
||||
placeholders[i] = ["_placeholder": true, "num": placeNum]
|
||||
datas.append(self.createBinaryDataForSend(arr[i] as NSData))
|
||||
placeNum++
|
||||
} else {
|
||||
placeholders[i] = arr[i]
|
||||
}
|
||||
}
|
||||
|
||||
if hadBinary {
|
||||
str = Event.createMessageForEvent(event, withArgs: [placeholders],
|
||||
hasBinary: true, withDatas: datas.count)
|
||||
|
||||
self.io?.send(str)
|
||||
for data in datas {
|
||||
self.io?.send(data)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
frame = Event(event: event, args: args)
|
||||
str = frame.createMessage()
|
||||
if args == nil {
|
||||
str = "42[\"\(event)\"]"
|
||||
} else {
|
||||
str = Event.createMessageForEvent(event, withArgs: [args!], hasBinary: false)
|
||||
}
|
||||
|
||||
// println("Sending: \(str)")
|
||||
self.io?.send(str)
|
||||
}
|
||||
|
||||
// Sends a message with multiple args
|
||||
// If a message contains binary we have to send those
|
||||
// seperately.
|
||||
func emitMultiple(event:String, args:AnyObject...) {
|
||||
if !self.connected {
|
||||
return
|
||||
}
|
||||
|
||||
var frame:Event
|
||||
var str:String
|
||||
var items = [AnyObject](count: args.count, repeatedValue: 1)
|
||||
var numberOfPlaceholders = -1
|
||||
var hasBinary = false
|
||||
var datas = [NSData]()
|
||||
|
||||
for i in 0..<args.count {
|
||||
if let dict = args[i] as? NSDictionary {
|
||||
// Check for binary data
|
||||
let (newDict, hadBinary, binaryDatas) = self.parseNSDictionary(dict,
|
||||
placeholders: numberOfPlaceholders + 1)
|
||||
if hadBinary {
|
||||
numberOfPlaceholders = binaryDatas!.count
|
||||
|
||||
for data in binaryDatas! {
|
||||
let sendData = self.createBinaryDataForSend(data)
|
||||
datas.append(sendData)
|
||||
}
|
||||
hasBinary = true
|
||||
items[i] = newDict
|
||||
continue
|
||||
}
|
||||
items[i] = dict
|
||||
} else if let arr = args[i] as? NSArray {
|
||||
// arg is array, check for binary
|
||||
var replacementArr = [AnyObject](count: arr.count, repeatedValue: 1)
|
||||
for g in 0..<arr.count {
|
||||
if arr[g] is NSData {
|
||||
hasBinary = true
|
||||
numberOfPlaceholders++
|
||||
|
||||
let sendData = self.createBinaryDataForSend(arr[g] as NSData)
|
||||
|
||||
datas.append(sendData)
|
||||
replacementArr[g] = ["_placeholder": true,
|
||||
"num": numberOfPlaceholders]
|
||||
} else {
|
||||
replacementArr[g] = arr[g]
|
||||
}
|
||||
}
|
||||
items[i] = replacementArr
|
||||
} else if let binaryData = args[i] as? NSData {
|
||||
// args is just binary
|
||||
hasBinary = true
|
||||
let sendData = self.createBinaryDataForSend(binaryData)
|
||||
|
||||
numberOfPlaceholders++
|
||||
items[i] = ["_placeholder": true, "num": numberOfPlaceholders]
|
||||
datas.append(sendData)
|
||||
} else {
|
||||
items[i] = args[i]
|
||||
}
|
||||
}
|
||||
|
||||
if hasBinary {
|
||||
str = Event.createMessageForEvent(event, withArgs: items,
|
||||
hasBinary: true, withDatas: datas.count)
|
||||
self.io?.send(str)
|
||||
for data in datas {
|
||||
self.io?.send(data)
|
||||
}
|
||||
} else {
|
||||
str = Event.createMessageForEvent(event, withArgs: items, hasBinary: false)
|
||||
self.io?.send(str)
|
||||
}
|
||||
}
|
||||
|
||||
// Handles events
|
||||
func handleEvent(#event:String, data:AnyObject?) {
|
||||
func handleEvent(#event:String, data:AnyObject?, multipleItems:Bool = false) {
|
||||
// println("Should do event: \(event) with data: \(data)")
|
||||
|
||||
for handler in self.handlers {
|
||||
if handler.event == event {
|
||||
if handler.event == event && !multipleItems {
|
||||
if data == nil {
|
||||
handler.executeCallback(nil)
|
||||
continue
|
||||
}
|
||||
|
||||
handler.executeCallback(data)
|
||||
} else if handler.event == event && multipleItems {
|
||||
if let arr = data as? [AnyObject] {
|
||||
handler.executeCallback(arr)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds handlers to the socket
|
||||
// Adds handler for single arg message
|
||||
func on(name:String, callback:((data:AnyObject?) -> Void)) {
|
||||
let handler = EventHandler(event: name, callback: callback)
|
||||
self.handlers.append(handler)
|
||||
}
|
||||
|
||||
// Adds handler for multiple arg message
|
||||
func onMultipleArgs(name:String, callback:((data:[AnyObject]) -> Void)) {
|
||||
let handler = EventHandler(event: name, callback: callback)
|
||||
self.handlers.append(handler)
|
||||
}
|
||||
|
||||
// Opens the connection to the socket
|
||||
func open() {
|
||||
self.connect()
|
||||
}
|
||||
|
||||
// Parses data for events
|
||||
private func parseData(data:String?) -> AnyObject? {
|
||||
class func parseData(data:String?) -> AnyObject? {
|
||||
if data == nil {
|
||||
return nil
|
||||
}
|
||||
@ -192,9 +309,9 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
}
|
||||
|
||||
// Parses a NSDictionary, looking for NSData objects
|
||||
private func parseNSDictionary(#dict:NSDictionary) -> (NSDictionary, Bool, [NSData]?) {
|
||||
private func parseNSDictionary(dict:NSDictionary, placeholders:Int = 0) -> (NSDictionary, Bool, [NSData]?) {
|
||||
var returnDict = NSMutableDictionary()
|
||||
var placeholder = 0
|
||||
var placeholder = placeholders
|
||||
var containedData = false
|
||||
var returnDatas = [NSData]()
|
||||
for (key, value) in dict {
|
||||
@ -262,13 +379,22 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
data = messageInternals[2]
|
||||
}
|
||||
|
||||
if let json:AnyObject = self.parseData(data) {
|
||||
self.handleEvent(event: event, data: json)
|
||||
// It would be nice if socket.io only allowed one thing
|
||||
// per message, but alas, it doesn't.
|
||||
if let parsed:AnyObject = SocketIOClient.parseData(data) {
|
||||
self.handleEvent(event: event, data: parsed)
|
||||
return
|
||||
} else if let strData = data {
|
||||
// There are multiple items in the message
|
||||
// Turn it into a String and run it through
|
||||
// parseData to try and get an array.
|
||||
let asArray = "[\(strData)]"
|
||||
|
||||
if let parsed:AnyObject = SocketIOClient.parseData(asArray) {
|
||||
self.handleEvent(event: event, data: parsed, multipleItems: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
self.handleEvent(event: event, data: data)
|
||||
return
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -286,12 +412,12 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
}
|
||||
|
||||
// Tries to parse a message that contains binary
|
||||
func parseBinaryMessage(#message:AnyObject) {
|
||||
private func parseBinaryMessage(#message:AnyObject) {
|
||||
if let stringMessage = message as? String {
|
||||
var mutMessage = RegexMutable(stringMessage)
|
||||
|
||||
/**
|
||||
Begin check for binary placeholder
|
||||
Begin check for binary placeholders
|
||||
**/
|
||||
let binaryGroup = mutMessage["(\\d*)-\\[\"(.*)\",(\\{.*\\})\\]$"].groups()
|
||||
|
||||
@ -301,28 +427,50 @@ class SocketIOClient: NSObject, SRWebSocketDelegate {
|
||||
let numberOfPlaceholders = messageType["45"] ~= ""
|
||||
let event = binaryGroup[2]
|
||||
let mutMessageObject = RegexMutable(binaryGroup[3])
|
||||
let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"] ~= "\"~~$2\""
|
||||
let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"]
|
||||
~= "\"~~$2\""
|
||||
let mes = Event(event: event, args: placeholdersRemoved,
|
||||
placeholders: numberOfPlaceholders.integerValue)
|
||||
self.lastSocketMessage = mes
|
||||
return
|
||||
} else {
|
||||
// There are multiple items in binary message
|
||||
let binaryGroups = mutMessage["(\\d*)-\\[(\".*?\"),(.*)\\]$"].groups()
|
||||
if binaryGroups != nil {
|
||||
let messageType = RegexMutable(binaryGroups[1])
|
||||
let numberOfPlaceholders = messageType["45"] ~= ""
|
||||
let event = RegexMutable(binaryGroups[2] as String)["\""] ~= ""
|
||||
let mutMessageObject = RegexMutable(binaryGroups[3])
|
||||
let placeholdersRemoved = mutMessageObject["(\\{\"_placeholder\":true,\"num\":(\\d*)\\})"]
|
||||
~= "\"~~$2\""
|
||||
let mes = Event(event: event, args: placeholdersRemoved,
|
||||
placeholders: numberOfPlaceholders.integerValue)
|
||||
self.lastSocketMessage = mes
|
||||
return
|
||||
}
|
||||
}
|
||||
/**
|
||||
End check for binary placeholder
|
||||
End check for binary placeholders
|
||||
**/
|
||||
}
|
||||
}
|
||||
|
||||
// Handles binary data
|
||||
func parseBinaryData(data:NSData) {
|
||||
private func parseBinaryData(data:NSData) {
|
||||
let shouldExecute = self.lastSocketMessage?.addData(data)
|
||||
|
||||
if shouldExecute != nil && shouldExecute! {
|
||||
var event = self.lastSocketMessage!.event
|
||||
var parsedArgs:AnyObject? = self.parseData(self.lastSocketMessage!.args as? String)
|
||||
var parsedArgs:AnyObject? = SocketIOClient.parseData(self.lastSocketMessage!.args as? String)
|
||||
|
||||
if let args:AnyObject = parsedArgs {
|
||||
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders(args)
|
||||
self.handleEvent(event: event, data: filledInArgs)
|
||||
} else {
|
||||
// We have multiple items
|
||||
let filledInArgs:AnyObject = self.lastSocketMessage!.fillInPlaceholders()
|
||||
self.handleEvent(event: event, data: filledInArgs, multipleItems: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user