I am trying to connect to an XMPP server in my iOS Application. I am using the XMPPFrameworks and for some reason the XMPP Stream delegate is not being called after I try to connect to the server. I have double checked the login information using a third party XMPP application on my computer so I do not believe it is that. Am I not setting this delegate up correctly? Am I using the wrong syntax? Do I need to set this in the app delegate instead of my view controller? Any help would be much appreciated. Below is my code
import UIKit
import XMPPFramework
class ViewController: UIViewController, XMPPStreamDelegate {
override func viewDidLoad() {
super.viewDidLoad()
connect()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func connect() {
let stream = XMPPStream()
stream?.addDelegate(self, delegateQueue: DispatchQueue.main)
stream?.myJID = XMPPJID.init(string: "XXXXXXXXXXX")
stream?.hostName = "XXXXXXXXX"
stream?.hostPort = 5222
do {
try stream?.connect(withTimeout: XMPPStreamTimeoutNone)
} catch {
print("error connecting")
}
}
func xmppStreamDidConnect(sender: XMPPStream) {
print("connected!")
do {
try sender.authenticate(withPassword: "XXXXXXXXXX")
} catch {
print("error registering")
}
}
}
I think that your delegate method is not right. You can try with the delegate method given below:
#objc func xmppStreamDidConnect(_ sender: XMPPStream!) {
//write your code here.
}
try this
do {
try self.xmppController = XMPPController(hostName: server,
userJIDString: userJID,
password: userPassword)
self.xmppController.xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
self.xmppController.connect()
} catch {
sender.showErrorMessage(message: "Something went wrong")
}
and XMPPController
class XMPPController: NSObject {
var xmppStream: XMPPStream
let hostName: String
let userJID: XMPPJID
let hostPort: UInt16
let password: String
init(hostName: String, userJIDString: String, hostPort: UInt16 = 5222, password: String) throws {
guard let userJID = XMPPJID(string: userJIDString) else {
throw XMPPControllerError.wrongUserJID
}
self.hostName = hostName
self.userJID = userJID
self.hostPort = hostPort
self.password = password
// Stream Configuration
self.xmppStream = XMPPStream()
self.xmppStream.hostName = hostName
self.xmppStream.hostPort = hostPort
self.xmppStream.startTLSPolicy = XMPPStreamStartTLSPolicy.allowed
self.xmppStream.myJID = userJID
super.init()
self.xmppStream.addDelegate(self, delegateQueue: DispatchQueue.main)
}
func connect() {
if !self.xmppStream.isDisconnected() {
return
}
try! self.xmppStream.connect(withTimeout: XMPPStreamTimeoutNone)
}}
it works for me. required your attention this line
try self.xmppController = XMPPController(hostName: server,
userJIDString: userJID,
password: userPassword)
I had the same issue. In my case (as I followed some tutorial) the object was not global and the delegate became nil. That's why it was not called. You have to store the object which implements XMPPStreamDelegate globally.
Related
i have a list of music at my firebase real time database and i am retriving them but i have 1000 musics data and i want to show loader when i reading data and stop loader when if there is a error(internet connection, or something else) or reading completed.
when i turn off the internet i couldn't get the data and can't stop loader to show error alert like there is no internet connection.
please help me how to handle that problem.
here is my code
didload function called from viewdidload()
private var musicArray = [ItemModal]() {
didSet {
view?.updateTableView()
}
}
func didLoad() {
view?.showLoader()
getAllMusics { ItemModal in
self.musicArray = ItemModal
self.view?.hideLoader()
}
}
func getAllMusics(completion: #escaping ([ItemModal]) -> Void) {
var musicArray = [ItemModal]()
ref.child("music").observeSingleEvent(of: .value) { snapshot in
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
guard let data = try? JSONSerialization.data(withJSONObject: rest.value as Any, options: []) else { return }
if let itemModal = try? JSONDecoder().decode(ItemModal.self, from: data) {
musicArray.append(itemModal)
}
}
completion(musicArray)
}
}
You can use reachability function by using https://github.com/ashleymills/Reachability.swift. To get to notify when the internet is turned off, you can implement reachabilityChanged Notification. In the selector method of reachabilityChanged, you can hide the loader.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged), name: .reachabilityChanged)
}
#objc func changed() {
if reachability?.isReachable {
//Continue success implementation
} else {
view?.hideLoder
//Implement Error handling
}
}
first of all thank you for reading my lines.
For an idea I'm currently trying to dive into the Swift world (I only have very basic programming knowledge - no Objective C knowledge
).
I tried to set up the following lines to create a very basic app-to-app sample in Sinch. After my code I let you know what the issues are.
import UIKit
import Sinch
var appKey = "APP_KEY_FROM_MY_ACCOUNT"
var hostname = "clientapi.sinch.com"
var secret = "SECRET_FROM_MY_ACCOUNT"
class CViewController: UIViewController, SINCallClientDelegate, SINCallDelegate, SINClientDelegate {
var client: SINClient?
var call: SINCall?
var audio: SINAudioController?
//Text field in the main storyboard
#IBOutlet weak var userNameSepp: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.initSinchClient()
}
//initialize and start the client as a fixed "userA"
func initSinchClient() {
client = Sinch.client(withApplicationKey: appKey, applicationSecret: secret, environmentHost: hostname, userId: "userB")
client?.call().delegate = self
client?.delegate = self
client?.startListeningOnActiveConnection()
client?.setSupportCalling(true)
client?.start()
}
//Did the Client start?
func clientDidStart(_ client: SINClient!) {
print("Hello")
}
//Did the Client fail?
func clientDidFail(_ client: SINClient!, error: Error!) {
print("Good Bye")
}
//Call Button in the main.storyboard ... if call==nil do the call ... else hangup and set call to nil
//the background color changes are my "debugging" :D
#IBAction func callSepp(_ sender: Any) {
if call == nil{
call = client?.call()?.callUser(withId: userNameSepp.text)
//for testing I change to callPhoneNumber("+46000000000").
// the phone call progresses (but I hear nothing),
// the phonecall gets established (but I hear nothing)
// and the phonecall gets ended (but of course I hear nothing)
self.view.backgroundColor = UIColor.red
call?.delegate = self
audio = client?.audioController()
}
else{
call?.hangup()
self.view.backgroundColor = UIColor.blue
call = nil
}
}
func callDidProgress(_ call: SINCall?) {
self.view.backgroundColor = UIColor.green
client?.audioController().startPlayingSoundFile("/LONG_PATH/ringback.wav", loop: true)
print("Call in Progress")
}
//I know that this works but I don't hear anything
func callDidEstablish(_ call: SINCall!) {
client?.audioController().stopPlayingSoundFile()
print("Call did Establish")
}
func callDidEnd(_ call: SINCall!) {
print("Call did end")
}
// this works fine
#IBAction func hangUpSepp(_ sender: Any) {
call?.hangup()
self.view.backgroundColor = UIColor.red
call = nil
}
// i work in a "sub view controller" - so i navigate here back to the main view controller
#IBAction func goBackMain(_ sender: Any) {
call?.hangup()
dismiss(animated: true, completion: nil)
client?.stopListeningOnActiveConnection()
client?.terminateGracefully()
client = nil
}
}
So I can call my private phone number or if I change to callUser I can call another app but I don't hear anything. What do I miss? It must have to do with the SINAudioController and the client's method audioController() but I don't know what I'm doing wrong. Thank you for your help.
A new Swift guy here. I'm trying to figure out how to chain multiple Alamofire calls together.
I need to
get an auth token from Server 1
get some data from Server 1 (need the auth token)
get an auth token from Server 2
Get more data from Server 2 based on the values from step 2.
I've tried following the examples on this post:
Chain multiple Alamofire requests
Unfortunately none of those examples are working with Swift 4.
I've decided to pursue Option 2, but keep getting a
Cannot call value of non-function type 'HTTPURLResponse?'
error both on the putRequest and getRequest lines. I have no idea what that means or how to fix it.
My current code:
import UIKit
import PromiseKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController {
let URL = "http://httpbin.org/"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func runPutRequest() {
let putRequest = Alamofire.request("\(URL)/get")
putRequest.response { [weak self] putRequest, putResponse, putData, putError in
if let strongSelf = self {
// Probably store some data
strongSelf.runGetRequest()
}
}
}
func runGetRequest() {
let getRequest = Alamofire.request("\(URL)/get", method: .get)
getRequest.response { [weak self] getRequest, getResponse, getData, getError in
if let strongSelf = self {
// Probably store more data
strongSelf.processResponse()
}
}
}
func processResponse() {
// Process that data
}
func reloadData() {
// Reload that data
}
}
Any help would be greatly appreciated.
You have too many return arguments for the response closures, you actually just need one DataResponse argument. This code is working for me:
func runPutRequest() {
let putRequest = Alamofire.request("\(URL)/get", method: .put)
putRequest.response { [weak self] response in
if let strongSelf = self {
// Probably store some data
strongSelf.runGetRequest()
}
}
}
func runGetRequest() {
let getRequest = Alamofire.request("\(URL)/get", method: .get)
getRequest.response { [weak self] response in
if let strongSelf = self {
// Probably store more data
strongSelf.processResponse()
}
}
}
I want to execute a function when there is an socket connection. But the methods can be fired immediately when there is an connection. The connection must be made when there isn't one.
What is an nice and proper way to solve this?
import SocketIO
class SocketIOManager: NSObject {
static let sharedInstance = SocketIOManager()
var socket: SocketIOClient = SocketIOClient(socketURL: NSURL(string: "http://192.168.1.59:3000")! as URL)
var connectionMade = false;
override init() {
super.init()
}
func establishConnection(completionHandler: (() -> Void)!) {
if(!connectionMade){
socket.connect()
connectionMade = true;
}
completionHandler();
}
func connectToRoom(roomNumber: String){
establishConnection {
self.socket.emit("connectToRoom", roomNumber);
}
}
}
Is this an good setup? And yes I have to set the bool to false when the connection is closed:)
I ask this because I have a problem with my code. I call this at the app delegate to made an connection:
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
SocketIOManager.sharedInstance.establishConnection {
}
}
And this at my view controller:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
SocketIOManager.sharedInstance.connectToRoom(self.roomNumber);
}
But the server is never getting the connectToRoom 'message'. It works when I push on a button with this code in it:
SocketIOManager.sharedInstance.connectToRoom(self.roomNumber);
So it looks like the socket connection isnt made at the viewdidload. But why does it work when I push the button? Because i'm waiting for an callback at the at the connectTo Room function from the connection at the SocketIOManger class.
just add a listener on connect like below:
socket.on(clientEvent: .connect) { [unowned self] data, ack in
print("socket connected")
print(data)
if !self.HasConnected {
// JOIN YOUR ROOM
self.HasConnected = true
}
}
I want to advertise some characteristics from an iPhone acting as a peripheral, but although the service seems to contain the characteristics they don't show up when you look at it with a BLE scanner, the service works fine and displays the localNameKey.
thanks
import UIKit
import CoreBluetooth
class ViewController: UIViewController, CBPeripheralManagerDelegate{
var peripheralManager: CBPeripheralManager!
let myCustomServiceUUID: CBUUID = CBUUID(string: "B5893BC9-63AB-42A5-BB33-EEAE686BED1D")
let myCustomCharacteristic: CBUUID = CBUUID(string: "9BA41369-C5B7-456B-B4E3-BB0A8DFF3A95")
let myCustomCharacteristic2: CBUUID = CBUUID(string: "9BA41369-C5B7-456B-B4E3-BB0A8DFF3A85")
var myService: CBMutableService!
var myCharacteristics: CBMutableCharacteristic!
var myCharacteristics2: CBMutableCharacteristic!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
myService = CBMutableService(type: myCustomServiceUUID, primary: true)
myCharacteristics = CBMutableCharacteristic(type: myCustomCharacteristic, properties: CBCharacteristicProperties.Broadcast, value: nil, permissions: CBAttributePermissions.Readable)
myCharacteristics2 = CBMutableCharacteristic(type: myCustomCharacteristic2, properties: CBCharacteristicProperties.Broadcast, value: nil, permissions: CBAttributePermissions.Readable)
myService.characteristics = [myCharacteristics, myCharacteristics2]
peripheralManager.addService(myService)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager) {
if peripheral.state == CBPeripheralManagerState.PoweredOn {
let dataTobeAdvetised :[String: AnyObject!] = [CBAdvertisementDataServiceUUIDsKey: [myService.UUID], CBAdvertisementDataLocalNameKey: "MY Device"]
self.peripheralManager.startAdvertising(dataTobeAdvetised)
print(myService)
print("It should be working!........")
} else if peripheral.state == CBPeripheralManagerState.PoweredOff {
self.peripheralManager.stopAdvertising()
}
}
}
You aren't permitted to use CBCharacteristic.broadcast property value.
From the documentation -
CBCharacteristicPropertyBroadcast
The characteristic’s value can be broadcast using a characteristic
configuration descriptor.
This property is not allowed for local characteristics published via
the addService: method of the CBPeripheralManager class. This means
that you cannot use this property when you initialize a new
CBMutableCharacteristic object via the
initWithType:properties:value:permissions: method of the
CBMutableCharacteristic class.
You should use some combination of CBCharacteristicPropertyRead, CBCharacteristicPropertyWriteWithoutResponse and CBCharacteristicPropertyWrite depending on your requirements.
Old question, but hopefully this will help somebody else. I was struggling with the same issue, but for me there was no didAddService callback. Turns out GATT initialisation should be after the peripheral state has changed to PoweredOn.
func peripheralManagerDidUpdateState(peripheral: CBPeripheralManager) {
if peripheral.state == CBPeripheralManagerState.PoweredOn {
//Do initialisation and then start advertising.
}
}