Use a protocol between a class and a view controller Swift 3 - ios

I worked with the library SwiftSocket to send messages to my server. When the connexion is established I want to create a callback to catch results. But my protocol is always null and the callback is not send.
This is my TCPClient class :
protocol ProtocolTCPClient {
func connexionSucceeded()
}
class UtilsTCPClient {
var delegate: ProtocolTCPClient?
let client: TCPClient?
init(address: String, port: Int32) {
client = TCPClient(address: address, port: port)
switch client!.connect(timeout: 5) {
case .success:
print("Success")
if(delegate != nil){
self.delegate?.connexionSucceeded()//never called
} else{
print("delegate nil")
}
case .failure(let error):
print("Error: ")
print(error)
}
}
}
This is my ViewController
import UIKit
import SwiftSocket
class ViewController: UIViewController, ProtocolTCPClient {
var client: UtilsTCPClient?
override func viewDidLoad() {
super.viewDidLoad()
self.client = UtilsTCPClient(address: "server", port: 80)
self.client?.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func connexionSucceeded(){
print("Connexion succeeded")//never called
}
}
Thank you for your answers

your code should look like this.Because in your code first you init 'UtilsTCPClient' and then assigning delegate. And in 'UtilsTCPClient' you create 'TCPClient' and trying to access delegate but till it't not assigned so you should try the below code.
protocol ProtocolTCPClient {
func connexionSucceeded()
}
class UtilsTCPClient {
var delegate: ProtocolTCPClient?
let client: TCPClient?
init(address: String, port: Int32, delegate: ProtocolTCPClient) {
self.delegate = delegate
client = TCPClient(address: address, port: port)
switch client!.connect(timeout: 5) {
case .success:
print("Success")
if(delegate != nil){
self.delegate?.connexionSucceeded()
} else{
print("delegate nil")
}
case .failure(let error):
print("Error: ")
print(error)
}
}
}
class ViewController: UIViewController, ProtocolTCPClient {
var client: UtilsTCPClient?
override func viewDidLoad() {
super.viewDidLoad()
self.client = UtilsTCPClient(address: "server", port: 80, delegate: self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func connexionSucceeded(){
print("Connexion succeeded")//never called
}
}

Related

Swift Socket Sever disconnected while moving to one view controller to other

I am trying to implement swift socket in my application. I am pretty new to socket programming. I have used
https://github.com/swiftsocket/SwiftSocket
for socket connection. I had create NSObject class for Server Connection.
I want Server connected through out my whole application, But Server is disconnected while I'm moving into another ViewController.
class SocketGLobal : NSObject
{
func Connect()
{
let client = TCPClient(address: "www.apple.com", port: 80)
switch client.connect(timeout: 1) {
case .success:
switch client.send(string: "GET / HTTP/1.0\n\n" ) {
case .success:
guard let data = client.read(1024*10) else { return }
if let response = String(bytes: data, encoding: .utf8) {
print(response)
}
case .failure(let error):
print(error)
}
case .failure(let error):
print(error)
}
}
}
I faced the same problem. So I created the custom ViewController and used GCDAsyncUdpSocket for socket connection. In your pod file add pod 'CocoaAsyncSocket' to use GCDAsyncUdpSocket. Here is the code snippet for custom ViewController.
import CocoaAsyncSocket
class CustomViewController: UIViewController, GCDAsyncUdpSocketDelegate {
//MARK: VARIABLE DECLARATION **********
var _udpSocket: GCDAsyncUdpSocket?
var udpSocket: GCDAsyncUdpSocket? {
get {
if _udpSocket == nil {
let port = 80
let sock = GCDAsyncUdpSocket(delegate: self, delegateQueue: DispatchQueue.main)
do {
sock.setIPv6Enabled(false)
// sock?.setIPv4Enabled(true)
// sock?.setPreferIPv4()
try sock.enableBroadcast(true)
try sock.bind(toPort: UInt16(port))
try sock.beginReceiving()
} catch let err as NSError {
print(">>> Error while initializing socket: \(err.localizedDescription)")
sock.close()
return nil
}
_udpSocket = sock
}
return _udpSocket
}
set {
_udpSocket?.close()
_udpSocket = newValue
}
}
//MARK: UDP SERVICES *********
//Start UDP Receiver
func startUDPService(){
guard udpSocket != nil else {
return
}
}
//Stop UDP Receiver
func closeUDPService(){
if udpSocket != nil {
udpSocket?.close()
udpSocket = nil
}
}
//MARK: HANDLING OF RECEIVED DATA **********
func udpSocket(_ sock: GCDAsyncUdpSocket, didReceive data: Data, fromAddress address: Data, withFilterContext filterContext: Any?) {
var hostPtr : NSString? = nil
GCDAsyncUdpSocket.getHost(&hostPtr, port: &send_port, fromAddress: address)
var receivedText = ""
if let stringData = String(data: data as Data, encoding: String.Encoding.utf8) {
receivedText = stringData
}
print("Data received: \(String(describing: hostPtr)), \(receivedText)")
}
}
In your each ViewController implement as follows:
import UIKit
class YourViewController: CustomViewController {
//MARK: LIFE CYCLE METHODS **********
override func viewWillAppear(_ animated: Bool) {
//MARK: START UDP SERVICE
self.startUDPService()
}
override func viewWillDisappear(_ animated: Bool) {
//MARK: STOP UDP SERVICE
self.closeUDPService()
}
}
I hope this will help you.

How to make function for HTTP request on other class in Swift?

I'm writing a app to make a http requests with SwiftHTTP, but I want to create a class to make this, and in the ViewController I call the functions to do this. So, I create a UIButton to call the functions.
I don't know if I need use threads or exists ways to make this easy.
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
button.addTarget(self,action:#selector(self.clickRequest(sender:)), for: UIControlEvents.touchUpInside )
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func clickRequest (sender: UIButton) {
}
}
HTTPService.swift
import Foundation
import SwiftHTTP
class HTTPService {
}
How I make this in others Apps. But inside of ViewController.swift.
HTTP.GET("https://www.host.com/example",requestSerializer: JSONParameterSerializer()) {
response in
if let err = response.error {
print(err.localizedDescription)
return
}
} catch let err as NSError {
print(err)
}
}
Create one method with successBlock and failureBlock inside your HTTPService service class like below,
class HTTPService {
func makeRequest(params: [String: Any], successBlock: () -> Void, failureBlock: () -> Void) {
HTTP.GET("https://www.host.com/example",requestSerializer: JSONParameterSerializer()) {
response in
if let err = response.error {
print(err.localizedDescription)
failureBlock() // Call failure block
return
} else {
successBlock() // Call success block
}
} catch let err as NSError {
print(err)
failureBlock() // Call failure block
}
}
}
You can call this method like below,
#objc func clickRequest (sender: UIButton) {
HTTPService().makeRequest(params: ["name": "userName"], successBlock: {
// Handle API success here. E.g Reloading table view
}) {
// Handle API failure here. E.g Showing error to user
}
}
Thanks

Delegated functions not working outside of UIViewController

I'm using the Startscream Websocket framework. Everything works fine as long as I keep all of the code in a UIViewController as seen here. But as soon as a create a wrapper class for Startscream all of the delegated functions stop working. Also my local websocket server is not getting a connection.
How can I get the code working inside a wrapper class?
MyService.swift:
import Starscream
public class MyService: WebSocketDelegate {
var socket = WebSocket(url: URL(string: "ws://localhost:3900/websocket")!)
func connect() {
socket.delegate = self
socket.connect()
print("Connecting")
}
// MARK: Websocket Delegate Methods.
public func websocketDidConnect(socket: WebSocket) {
print("websocket is connected")
}
public func websocketDidDisconnect(socket: WebSocket, error: NSError?) {
if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
public func websocketDidReceiveMessage(socket: WebSocket, text: String) {
print("Received text: \(text)")
}
public func websocketDidReceiveData(socket: WebSocket, data: Data) {
print("Received data: \(data.count)")
}
// MARK: Write Text Action
#IBAction func writeText(_ sender: UIBarButtonItem) {
socket.write(string: "hello there!")
}
// MARK: Disconnect Action
#IBAction func disconnect(_ sender: UIBarButtonItem) {
if socket.isConnected {
sender.title = "Connect"
socket.disconnect()
} else {
sender.title = "Disconnect"
socket.connect()
}
}
}
ViewController.swift:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let service = MyService()
service.connect()
}
}
The reference to Service in ViewController was not stored anywhere so as soon as the function was run it was cleaned up. This is how I fixed it:
class ViewController: UIViewController {
var service = MyService()
override func viewDidLoad() {
super.viewDidLoad()
service.connect()
}
...
I'm not sure what is wrong with your code, it can be an endpoint issue, or WS is not allocated somehow. I have same code with Starscream working in Swift 3, here is the main part of my class.
class ConnectionManager {
private var savedSocket: WebSocket?
fileprivate var socket: WebSocket {
if let saved = savedSocket {
return saved
}
let wsURL = URL(string: UserDefaultsManager.wsURLString)!
savedSocket = WebSocket(url: wsURL)
return savedSocket!
}
func startSession() {
if (socket.isConnected) { return }
socket.headers = headers
socket.delegate = self
socket.connect()
}
func endSession() {
if (socket.isConnected) {
socket.disconnect()
}
}
}
extension ConnectionManager: WebSocketDelegate {
func websocketDidConnect(socket: WebSocket) {
}
func websocketDidDisconnect(socket: WebSocket, error: NSError?){
if let e = error {
log.error("websocket is disconnected with ERROR: \(e.localizedDescription)")
} else {
log.error("websocket disconnected")
}
}
func websocketDidReceiveMessage(socket: WebSocket, text: String){
}
func websocketDidReceiveData(socket: WebSocket, data: Data){
}
}
My code is not a best practise for sure, but it works without any problem. Try to use my version, maybe it will work for you.

Starscream delegates not being called

The variable is not nil, I have a good connection and the url is correct but no delegate methods are being called. Also I am implementing WebSocketDelegate
let socket = WebSocket(url: NSURL(string: "UrlHere:port/")!)
socket.delegate = self;
socket.connect()
if socket.isConnected {
print("websocket is connected")
}
func websocketDidConnect(ws: WebSocket) {
print("websocket is connected")
}
func websocketDidDisconnect(ws: WebSocket, error: NSError?) {
if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
func websocketDidReceiveMessage(ws: WebSocket, text: String) {
print("Received text: \(text)")
}
func websocketDidReceiveData(ws: WebSocket, data: NSData) {
print("Received data: \(data.length)")
}
func websocketDidReceivePong(socket: WebSocket) {
print("Got pong!")
}
Socket should be a property or variable of your class to make sure it sticks around.
If you allocate it just on a function stack it will fall out of scope and the delegates will never get called
Here is the code that I have used in my project just in case
import UIKit
//import WebSocket
import Starscream
class ViewController: UIViewController,WebSocketDelegate,WebSocketPongDelegate {
#IBOutlet weak var wsURL: UITextField!
#IBOutlet weak var wsConsole: UITextView!
#IBOutlet weak var wsMessage: UITextField!
var socket:WebSocket!
override func viewDidLoad() {
super.viewDidLoad()
// var webSocketObj:WebSocket = WebSocket()
// webSocketObj.ipAddressText = "10.12.1.101"
// webSocketObj.portText = "8888"
// webSocketObj.dataToSendText = "hi"
// webSocketObj.dataRecievedTextView = ""
// webSocketObj.connectedLabel = ""
// webSocketObj.connectToServer()
wsURL.text="ws://10.12.1.101:8888/"
wsMessage.text="Hi"
self.navigationItem.leftBarButtonItem?.title="Connect"
self.navigationItem.rightBarButtonItem?.enabled=false
// Do any additional setup after loading the view, typically from a nib.
}
func websocketDidConnect(socket: WebSocket){
wsConsole.text = wsConsole.text .stringByAppendingString("\n websocket got connected")
self.navigationItem.leftBarButtonItem?.title="Disconnect"
self.navigationItem.rightBarButtonItem?.enabled=true
}
func websocketDidDisconnect(socket: WebSocket, error: NSError?){
wsConsole.text = wsConsole.text .stringByAppendingString("\n websocket got disconnected")
self.navigationItem.leftBarButtonItem?.title="Connect"
self.navigationItem.rightBarButtonItem?.enabled=false
}
func websocketDidReceiveMessage(socket: WebSocket, text: String){
wsConsole.text = wsConsole.text .stringByAppendingString("\n websocket got a message from server:").stringByAppendingString(text)
}
func websocketDidReceiveData(socket: WebSocket, data: NSData){
print("websocket received data",data)
}
#IBAction func writeText(sender: UIBarButtonItem) {
wsConsole.text = wsConsole.text .stringByAppendingString("\n Client sent a message:").stringByAppendingString(wsMessage.text!)
socket.writeString(wsMessage.text!)
self.view .endEditing(true)
}
#IBAction func disconnect(sender: UIBarButtonItem) {
self.view .endEditing(true)
if socket == nil{
connect(sender)
}
else if socket.isConnected {
socket.disconnect()
} else {
connect(sender)
}
}
func connect(sender:UIBarButtonItem){
socket = WebSocket(url: NSURL(string:wsURL.text!)!)
socket.delegate = self
socket.connect()
}
func websocketDidReceivePong(socket: WebSocket){
wsConsole.text = wsConsole.text .stringByAppendingString("\n websocket received pong")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is the link to storyboard just in case if you want

How to Call Web Service in Web Socket in iOS?

currently i am making chat application using Web Socket.
My question is How to Call Web Service in Web Socket ?
In iOS using swift you can use two Cocoapods Library which makes your work hassle free and
1) Starscream
2) RocketSocket
With reference to Starscream follow are very handy example:
import UIKit
import Starscream
class ViewController: UIViewController, WebSocketDelegate {
var socket: WebSocket!
override func viewDidLoad() {
super.viewDidLoad()
var request = URLRequest(url: URL(string: "http://localhost:8080")!)
request.timeoutInterval = 5
socket = WebSocket(request: request)
socket.delegate = self
socket.connect()
}
// MARK: Websocket Delegate Methods.
func websocketDidConnect(socket: WebSocketClient) {
print("websocket is connected")
}
func websocketDidDisconnect(socket: WebSocketClient, error: Error?) {
if let e = error as? WSError {
print("websocket is disconnected: \(e.message)")
} else if let e = error {
print("websocket is disconnected: \(e.localizedDescription)")
} else {
print("websocket disconnected")
}
}
func websocketDidReceiveMessage(socket: WebSocketClient, text: String) {
print("Received text: \(text)")
}
func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
print("Received data: \(data.count)")
}
// MARK: Write Text Action
#IBAction func writeText(_ sender: UIBarButtonItem) {
socket.write(string: "hello there!")
}
// MARK: Disconnect Action
#IBAction func disconnect(_ sender: UIBarButtonItem) {
if socket.isConnected {
sender.title = "Connect"
socket.disconnect()
} else {
sender.title = "Disconnect"
socket.connect()
}
}
}

Resources