I am using latest version of SocketIOClient (13.1.1). How to emit or listen using namespace.
This should be enough :
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
let manager = SocketManager(socketURL: URL(string: "")!, config: [.log(false), .compress, .forcePolling(false)])
var avaialableCallBack:(([Any]) -> Void)?
override init(){
super.init()
}
func establishConnection() {
let socket = manager.socket(forNamespace: "/consumer")
socket.on("connect") { (data, ack) -> Void in
print("socket connected",data,ack)
}
socket.on(clientEvent: .disconnect){data, ack in
print("socket disconnected")
}
socket.on("session-available") { (dataArr, ack) -> Void in
ack.with(true)
if let sessionAvailableCB = self.avaialableCallBack {
sessionAvailableCB(dataArr)
}
}
socket.connect()
}
func closeConnection() {
let socket = manager.socket(forNamespace: "/consumer")
socket.disconnect()
}
func emitMessage(message:String,data:[String:Any]){
let socket = manager.socket(forNamespace: "/consumer")
socket.emit(message,data)
}
func emitMessageWithAck(message:String,data:[String:Any]) -> OnAckCallback{
let socket = manager.socket(forNamespace: "/consumer")
return socket.emitWithAck(message, data)
}
}
Related
I am new to using socket.io. I have made a singleton class for socket works and I am using an Instance of it in my app.
My question is: How to perform any action after receiving the data in the On function when I am on a different view controller?
import Foundation
import SocketIO
import UIKit
protocol testUI {
func fareUpdate(amount:NSNumber)
}
var delegate:testUI?
class SocketHelper {
static let shared = SocketHelper()
var socket: SocketIOClient!
let manager = SocketManager(socketURL: URL(string: "http://13.59.81.136:3355/")!, config: [.log(true), .compress, .connectParams(["token":user.shared.token])] )
private init() {
socket = manager.defaultSocket
}
func connectSocket(completion: #escaping(Bool) -> () ) {
disconnectSocket()
// socket.on(clientEvent: .connect) {[weak self] (data, ack) in
// print("socket connected")
// self?.socket.removeAllHandlers()
// completion(true)
// }
socket.connect()
}
func disconnectSocket() {
socket.removeAllHandlers()
socket.disconnect()
print("socket Disconnected")
}
func testStatus(){
print(socket.status)
}
func checkConnection() -> Bool {
if socket.manager?.status == .connected {
return true
}
return false
}
enum Events {
case search
func getFareEstimate(params:NSDictionary){
SocketHelper.shared.socket.emit("fareEstimate" , params)
}
func listen(completion: #escaping (Any) -> Void) {
SocketHelper.shared.socket!.on("rideFares") { (response, emitter) in
print(response)
let dic = response as! NSArray
let data = dic[0] as! NSDictionary
let fare = data["fare"] as! NSNumber
DispatchQueue.main.async {
delegate?.fareUpdate(amount: fare)
}
}
// func off() {
// SocketHelper.shared.socket.off(listnerName)
// }
}
}
}
I have tried using a delegate but it doesn't seem to work. I could be on multiple view controllers when the socket receives the data in the On function.
I am working on a personal project where I will be connecting the user to a VPN. I have followed two blog posts on doing this which are https://medium.com/better-programming/how-to-build-an-openvpn-client-on-ios-c8f927c11e80 & https://kean.blog/post/vpn-configuration-manager. I was able to configure the VPN settings but still, it does not connect. Here are the images for my project Signing & Capabilities one for the App and the other is for the network extension.
my ViewController looks like this. There is a folder in the user app document directory that is named user which gets downloaded from the internet and these are the files that are in the folder. I am not sure if I am supposed to use it other than the user.ovpn file
import UIKit
import Zip
import Alamofire
import NetworkExtension
class ViewController: UIViewController {
var selectedServer: Server?
var providerManager: NETunnelProviderManager!
override func viewDidLoad() {
super.viewDidLoad()
self.loadProviderManager {
self.configureVPN(serverAddress: "openvpn://\(self.selectedServer!.server.address):\(self.selectedServer!.server.port)", username: "\(self.username)", password: "\(self.password)")
}
}
func loadProviderManager(completion:#escaping () -> Void) {
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if error == nil {
self.providerManager = managers?.first ?? NETunnelProviderManager()
completion()
}
}
}
func configureVPN(serverAddress: String, username: String, password: String) {
guard let configData = self.readFile(path: "user/user.ovpn") else { return }
self.providerManager?.loadFromPreferences { error in
if error == nil {
let tunnelProtocol = NETunnelProviderProtocol()
tunnelProtocol.username = username
tunnelProtocol.serverAddress = serverAddress
tunnelProtocol.providerBundleIdentifier = "com.example.Networking.tunnel"
tunnelProtocol.providerConfiguration = ["ovpn": configData, "username": username, "password": password]
tunnelProtocol.disconnectOnSleep = false
self.providerManager.protocolConfiguration = tunnelProtocol
self.providerManager.localizedDescription = "OpenVPN"
self.providerManager.isEnabled = true
self.providerManager.saveToPreferences(completionHandler: { (error) in
if error == nil {
self.providerManager.loadFromPreferences(completionHandler: { (error) in
do {
try self.providerManager.connection.startVPNTunnel()
} catch let error {
print(error.localizedDescription)
}
})
}
})
}
}
}
func readFile(path: String) -> Data? {
let fileManager = FileManager.default
do {
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = documentDirectory.appendingPathComponent(path)
return try Data(contentsOf: fileURL, options: .uncached)
}
catch let error {
print(error.localizedDescription)
}
return nil
}
}
And my PacketTunnelProvider looks like this
import NetworkExtension
import OpenVPNAdapter
class PacketTunnelProvider: NEPacketTunnelProvider {
var startHandler: ((Error?) -> Void)?
var stopHandler: (() -> Void)?
var vpnReachability = OpenVPNReachability()
var configuration: OpenVPNConfiguration!
var properties: OpenVPNProperties!
var UDPSession: NWUDPSession!
var TCPConnection: NWTCPConnection!
lazy var vpnAdapter: OpenVPNAdapter = {
let adapter = OpenVPNAdapter()
adapter.delegate = self
return adapter
}()
override func startTunnel(options: [String : NSObject]?, completionHandler: #escaping (Error?) -> Void) {
guard
let protocolConfiguration = protocolConfiguration as? NETunnelProviderProtocol,
let providerConfiguration = protocolConfiguration.providerConfiguration
else {
fatalError()
}
guard let ovpnFileContent: Data = providerConfiguration["ovpn"] as? Data else { return }
let configuration = OpenVPNConfiguration()
configuration.fileContent = ovpnFileContent
do {
properties = try vpnAdapter.apply(configuration: configuration)
} catch {
completionHandler(error)
return
}
configuration.tunPersist = true
if !properties.autologin {
if let username: String = providerConfiguration["username"] as? String, let password: String = providerConfiguration["password"] as? String {
let credentials = OpenVPNCredentials()
credentials.username = username
credentials.password = password
do {
try vpnAdapter.provide(credentials: credentials)
} catch {
completionHandler(error)
return
}
}
}
vpnReachability.startTracking { [weak self] status in
guard status != .notReachable else { return }
self?.vpnAdapter.reconnect(afterTimeInterval: 5)
}
startHandler = completionHandler
vpnAdapter.connect()
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: #escaping () -> Void) {
stopHandler = completionHandler
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
vpnAdapter.disconnect()
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
if let handler = completionHandler {
handler(messageData)
}
}
override func sleep(completionHandler: #escaping () -> Void) {
completionHandler()
}
override func wake() {
}
}
extension PacketTunnelProvider: OpenVPNAdapterDelegate {
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: #escaping (OpenVPNAdapterPacketFlow?) -> Void) {
setTunnelNetworkSettings(networkSettings) { (error) in
completionHandler(error == nil ? self.packetFlow : nil)
}
}
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleEvent event: OpenVPNAdapterEvent, message: String?) {
switch event {
case .connected:
if reasserting {
reasserting = false
}
guard let startHandler = startHandler else { return }
startHandler(nil)
self.startHandler = nil
case .disconnected:
guard let stopHandler = stopHandler else { return }
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
stopHandler()
self.stopHandler = nil
case .reconnecting:
reasserting = true
default:
break
}
}
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, fatal == true else {
return
}
NSLog("Error: \(error.localizedDescription)")
NSLog("Connection Info: \(vpnAdapter.connectionInformation.debugDescription)")
if vpnReachability.isTracking {
vpnReachability.stopTracking()
}
if let startHandler = startHandler {
startHandler(error)
self.startHandler = nil
} else {
cancelTunnelWithError(error)
}
}
func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
NSLog("Log: \(logMessage)")
}
}
extension PacketTunnelProvider: OpenVPNAdapterPacketFlow {
func readPackets(completionHandler: #escaping ([Data], [NSNumber]) -> Void) {
packetFlow.readPackets(completionHandler: completionHandler)
}
func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
return packetFlow.writePackets(packets, withProtocols: protocols)
}
}
extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {}
I am trying to use socketIO for one of my projects.
I need to use following options while connecting to my socketIO server.
let socketConfig = SocketIOClientOption.self
socketConfig.forceNew(true)
socketConfig.reconnects(true)
socketConfig.reconnectAttempts(10)
socketConfig.reconnectWait(6000)
According to socketIO docs (https://github.com/socketio/socket.io-client-swift) I am not able to find a way to pass SocketIOOptions while connecting.
I have been trying to use below code to connect but it fails due to the absence of these options
let manager = SocketManager(socketURL: URL(string: "myurl:9476")!, config: [.log(true), .connectParams(["key":"value"])])
let socket = manager.defaultSocket
SocketIO version used:- 'Socket.IO-Client-Swift', '~> 13.3.0'
I figured out the solution.
The way to include options has been revised in the latest version.
I did the following and it worked:-
manager = SocketManager(socketURL: URL(string:"myurl:123")!, config: [.log(true), .forceNew(true), .reconnectAttempts(10), .reconnectWait(6000), .connectParams(["key":"value"]), .forceWebsockets(true), .compress])
socket = manager?.defaultSocket
Socket singleton class in Swift 4
import Foundation
import UIKit
import SwiftyJSON
import Alamofire
import SocketIO
import ObjectMapper
typealias OrderEventResponseBlock = (_ response : Any? , _ type : OrderEventType) -> ()
typealias TrackResponseBlock = (_ response : Any?) -> ()
class SocketIOManager: NSObject {
static let shared = SocketIOManager()
private var manager: SocketManager?
var socket: SocketIOClient?
override init() {
super.init()
let token = UDSingleton.shared.userData?.userDetails?.accessToken
guard let URL = URL(string: APIBasePath.basePath) else {return}
manager = SocketManager(socketURL: URL , config: [.log(true), .connectParams(["access_token" : /token])])
socket = manager?.defaultSocket
setupListeners()
}
//Server Methods
func establishConnection() {
let token = UDSingleton.shared.userData?.userDetails?.accessToken
if (self.socket?.status == .disconnected || self.socket?.status == .notConnected ) {
if (token != nil || token != "") {
socket?.connect()
}
}
else {
debugPrint("======= Socket already connected =======")
}
}
func closeConnection() {
debugPrint("=======***** SocketClientEvent.disconnect called ****=======")
socket?.disconnect()
}
func setupListeners() {
socket?.on(SocketClientEvent.disconnect.rawValue) { [weak self] (array, emitter) in
debugPrint("======= SocketClientEvent.disconnect listener=======")
self?.establishConnection()
}
socket?.on(SocketClientEvent.error.rawValue) {[weak self] (array, emitter) in
debugPrint("======= SocketClientEvent.error =======")
self?.establishConnection()
}
socket?.on(SocketClientEvent.connect.rawValue) { (array, emitter) in
if self.socket?.status == .connected {
debugPrint("======= userauth after connected =======")
}
}
}
func getStatus() -> SocketIOStatus? {
guard let status = self.socket?.status else{ return nil }
return status
}
//MARK:- Listening Events
//MARK:-
func listenOrderEventConnected(_ completionHandler: #escaping OrderEventResponseBlock) {
socket?.on(SocketEvents.OrderEvent.rawValue) {(arrData, socketAck) in
guard let item = JSON(arrData[0]).dictionaryObject else {return}
guard let type = item["type"] as? String else{return}
guard let typeSocket : OrderEventType = OrderEventType(rawValue: type) else {return}
}
}
//MARK:- EmitterWithAcknowledge Events
func emitMapLocation(_ userData : [String: Any] , _ completionHandler: #escaping TrackResponseBlock) {
socket?.emitWithAck(SocketEvents.CommonEvent.rawValue , userData).timingOut(after: 4.0, callback: { (response) in
guard let item = JSON(response[0]).dictionaryObject else{return}
let json = JSON(item)
if json[APIConstants.statusCode.rawValue].stringValue == Validate.successCode.rawValue {
let objDriver = Mapper<ApiSucessData<DriverList>>().map(JSONObject: item)
completionHandler( objDriver?.object)
}
})
}
func getParticularOrder(_ userData : [String: Any] , _ completionHandler: #escaping TrackResponseBlock) {
socket?.emitWithAck(SocketEvents.CommonEvent.rawValue, userData).timingOut(after: 2.0, callback: { (response) in
let item = JSON(response[0]).dictionaryObject
let json = JSON(item)
if json[APIConstants.statusCode.rawValue].stringValue == Validate.successCode.rawValue {
let objOrder = Mapper<ApiSucessData<Order>>().map(JSONObject: item)
completionHandler( objOrder?.object)
}
})
}
}
I have issue with soket.io client, and as I read here, you should define socket manager as a global variable so it's not released by ARC.
My code with that in mind:
let manager = SocketManager(socketURL: URL(string: Api.SOCKET)!, config: [.log(true), .path(Api.SOCKET_PATH)])
let socket: SocketIOClient?
....
override func viewDidLoad() {
super.viewDidLoad()
subscribeOnTransaction() { }
}
func subscribeOnTransaction() {
if self.socket == nil {
socket = manager.socket(forNamespace: Api.SOCKET_PATH)
subscribeToChangesChannel { }
socket?.on(clientEvent: .connect) { data, ack in
self.socket?.emit("transaction", self.sellOrder.id!)
}
self.socket?.on(clientEvent: .statusChange) {data, ack in
print(data)
}
self.socket?.connect()
}
}
func subscribeToChangesChannel(completion: #escaping () -> Void) {
if let socket = self.socket {
socket.on("transaction/\(self.sellOrder.id!)") { data, ack in
print(data, ack)
if data.count > 0 {
let rawResult = data[0]
if let result = rawResult as? [String: Any] {
let newRawValue = result["new_val"]
if let transaction = self.parseSocketResponse(newRawValue) {
self.openTransactionTrackingScreen(transaction)
completion()
}
}
}
}
}
}
But it doesn't call the handlers when I set breakpoints. Connection is established, everything's fine, with log turned on I get
Got polling response
LOG SocketEnginePolling: Got poll message:
What might be the problem? Any ideas? Will appreciate any help, thanks
Error :
Blockquote
it says "Argument labels '(String:)' do not match any available overloads"
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
let socket = SocketIOClient(manager: URL(String:"http://localhost:8080") as! URL, nsp: [.log(true), .forcePolling(true)])
// let socket = SocketIOClient(manager: URL(string: "http://localhost:8080")! as! SocketManagerSpec, nsp: [.log(true), .forcePolling(true)])
override init() {
super.init()
socket.on("test") { dataArray, ack in
print(dataArray)
}
}
How can I solve this.
any help would be apprciated.
I'd recommend you to read through the Socket IO documentation before trying to implement it. To get you started, you need to have a socketClient property in your Socket Manager class and you need to instantiate SocketClient before using Socket events.
class SocketManager {
//Socket IO client instance to emit and observe events of your socket
private let socketClient: SocketIOClient!
private init() {
let socketUrl = "Your Socket URL here"
socketClient = SocketIOClient(socketURL: URL(string: socketURL)!)
setupEvents()
}
func setupEvents() {
socket.on("test") { dataArray, ack in
print(dataArray)
}
}
Hope this helps you get started
I'd recommended below coding:
import SocketIO
let manager = SocketManager(socketURL: URL(string: "http://localhost:8080")!, config: [.log(true), .compress])
let socket = manager.defaultSocket
socket.on(clientEvent: .connect) {data, ack in
print("socket connected")
}
socket.on("currentAmount") {data, ack in
guard let cur = data[0] as? Double else { return }
socket.emitWithAck("canUpdate", cur).timingOut(after: 0) {data in
socket.emit("update", ["amount": cur + 2.50])
}
ack.with("Got your currentAmount", "dude")
}
socket.connect()