Messenger cannot connect to a XMPP server from the first attempt - ios

I wrote 2 functions:
if let stream = xmppStream {
if stream.isAuthenticated(){
println("Logged In")
} else {
println("something is wrong")
}
}
func xmppStreamDidConnect(sender: XMPPStream) {
println("xmppStreamDidConnect")
isOpen = true
var error: NSError?
if (xmppStream!.authenticateWithPassword(password.text, error: &error) ) {
println("authentification successful")
performSegueWithIdentifier("goToBuddyList", sender: nil)
}
}
And when I run my app it prints in the terminal:
something is wrong
xmppStreamDidConnect
authentification successful
Even if I putted true credentials it prints at first [something is wrong] and just later [authentification successful]. Why it happens?
I want alert users just in case of [something is wrong], not in [successful] case, but it alert it in successful case, too.

Implement xmppStreamDidAuthenticate and didNotAuthenticate methods of XMPPStreamDelegate .
After calling authenticateWithPassword client authentication will surely end up in above two function (xmppStreamDidAuthenticate and didNotAuthenticate) until then stream.isAuthenticated() will return “0”.

Related

How to run a function after setupIntentConfirmation succeeds?

I can successfully create and confirm a setupIntent. After the user enters his credit card details and presses the "confirm" button, his payment method is successfully attached to their stripe customer account. However, when the setupIntent is confirmed, I'd like to run a function on my client to send the user to a different screen.
This is where I check the completion of the setupIntentConfirmation. The print statement shows in the console but for some reason, my function is not running.
func onCompletion(status: STPPaymentHandlerActionStatus, si: STPSetupIntent?, error: NSError?) {
self.setupIntentStatus = status
self.error = error
if status == .succeeded {
print("succeeded")
setIsVerifiedToTrue()
}
}
Here is the function I am trying to run:
func setIsVerifiedToTrue() {
let ref = FirebaseReferenceManager.root.collection(FirebaseKeys.CollectionPath.requirements).document(Auth.auth().currentUser!.uid)
ref.updateData([FirebaseKeys.RequirementsFieldPath.verified : true]) { error in
if let error = error {
print("Error updating document: \(error)")
} else {
print("isVerified set to true")
}
}
}
any help would be very much appreciated! :)

Authentication failed and Try Face Id Again does nothing

I'm just follow this tutorial to authenticate user by Face ID but actually it's not work with "Try Face Id Again" button after authentication failed, the callback was not called and I don't know why.
Here is the code:
#IBAction func touchIdAction(_ sender: UIButton) {
print("hello there!.. You have clicked the touch ID")
let myContext = LAContext()
let myLocalizedReasonString = "Biometric Authntication testing !! "
var authError: NSError?
if #available(iOS 8.0, macOS 10.12.1, *) {
if myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
myContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString) { success, evaluateError in
DispatchQueue.main.async {
if success {
// User authenticated successfully, take appropriate action
self.successLabel.text = "Awesome!!... User authenticated successfully"
} else {
// User did not authenticate successfully, look at error and take appropriate action
self.successLabel.text = "Sorry!!... User did not authenticate successfully"
}
}
}
} else {
// Could not evaluate policy; look at authError and present an appropriate message to user
successLabel.text = "Sorry!!.. Could not evaluate policy."
}
} else {
// Fallback on earlier versions
successLabel.text = "Ooops!!.. This feature is not supported."
}
}
Running with Xcode 9.4.1 on iPhone X Simulator.
Thanks
Before tapping Try Face Id Again button you have to inform the simulator if it should simulate matching or non-matching face.
You can do it by selecting Hardware->Face ID->Matching Face/Non-matching Face
ANSWER:
I had the same problem. Then I checked in device and it works. So this doesn't work only in simulator

How can I get started with Quickblox API and Swift?

I am trying to develop a very simple chat application using quickblox and swift.
Knowing that there are few tutorials online that try to explain the process, I started with creating a user in the application dashboard and getting its credentials to initiate the connection. (I am certain that the user credential are correct and the dashboard is correctly set as I have followed this tutorial)
Here is the Application view controller:
import UIKit
import Quickblox
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let user = QBUUser()
user.id = 29777469
user.password = "tahrisqalli"
QBChat.instance().connect(with: user) { (error) in
if error != nil {
print("error: \(error)")
}
else {
print("login to chat succeeded")
}
}
}
}
and following is the error I get telling me that I did not connect successfully.
2017-07-11 11:33:50.837 QuickbloxTutorial[1045:24701] [ChatService] Connecting to Chat, host: chat.quickblox.com, user JID: 29777469-0#chat.quickblox.com/DCB0A1F4-3A56-49AD-9639-8C2A6BBE7B08
2017-07-11 11:33:52.042 QuickbloxTutorial[1045:24711] [ChatService] Stream isSecure: YES
2017-07-11 11:33:52.658 QuickbloxTutorial[1045:24722] [ChatService] Stream did connect, supportsStartTLS: YES
2017-07-11 11:33:52.824 QuickbloxTutorial[1045:24722] [ChatService] Did not authenticate, error: <failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>
error: Optional(Error Domain=com.quickblox.chat Code=401 "<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>" UserInfo={NSLocalizedDescription=<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><not-authorized/></failure>})
2017-07-11 11:33:52.842 QuickbloxTutorial[1045:24722] [ChatService] Did disconnect
First of all, you have to log in with a user.
After this, You can connect with chat and it is best for you to use ServicesManager class that manage session automatically.
let loginUser = QBUUser()
loginUser.id = 29777469
loginUser.password = "tahrisqalli"
ServicesManager.instance().authService.logInWithUser(loginUser, completion: { (response, qbUser) in
if qbUser != nil {
ServicesManager.instance().chatService.connectWithCompletionBlock { (error) in
if error != nil {
print("user not connected error: ",error?.description)
} else {
//user connect successfully
}
}
print(qbUser)
} else {
print(response.error?.description)
}
})

Problems With Error Casting In Swift

Not sure if this a bug or an intended feature.
To create a user with an email and password in Firebase, I've been using the following code:
FIRAuth.auth()?.signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
guard let error = error as? FIRAuthErrorCode else { return } // ALWAYS FAILS
...code...
}
...code...
}
The error parameter in the completion handler for the method cannot be cast as FIRAuthErrorCode; it always fails. Is that a bug, or is that the expected behaviour?
Edit: I am aware that error codes can be used to distinguish between the different types of FIRAuthErrorCode errors. It's just not readable, and it doesn't make much sense for the error parameter in the completion handler to be not of be of type FIRAuthErrorCode. The cases and error codes of FIRAuthErrorCode can be found here.
Have you tried using guard let error = error as! FIRAuthErrorCode else { return } to force the casting and check whether the return is nil or not?
After contacting Firebase support about the issue, they've said that the errors that are passed back in completion handlers are just Error objects. They weren't FIRAuthErrorCode objects. To test for the various FIRAuthErrorCode cases, one would have to do something like this:
FIRAuth.auth()?.signIn(withEmail: email, password: password) { (user, error) in
if let error = error {
guard let error = FIRAuthErrorCode(rawValue: error._code) else {
fatalError("This should never be executed")
}
switch error {
case .errorCodeInvalidEmail: ...
case .errorCodeWrongPassword: ...
default: ...
}
...code...
}
...code...
}
^ This preserves readability and makes error handling more intuitive. And, there is no need for error casting!
You should check the documentation of signIn method in firebase in order to check the all possible type of error this method can send and then check those type of errors in guard block in your code.
Try this, it's how I do my login and it seems to work great.
FIRAuth.auth()?.signIn(withEmail: EmailField.text!, password: PasswordField.text!, completion: { user, error in
if error == nil {
print("Successfully Logged IN \(user!)")
self.performSegue(withIdentifier: "Login", sender: self)
}
})
I just check that there's not an error with the signin process, then perform my segue.

How to identify iCloud logged in user in airplane mode?

I try to get userRecordID in airplane mode, but I get an error, any other way?
class func asdf() {
var defaultContainer = CKContainer.defaultContainer()
var publicDatabase = defaultContainer.publicCloudDatabase
defaultContainer.fetchUserRecordIDWithCompletionHandler({ userRecordID, error in
if error == nil {
println("userRecordID.recordName : \(userRecordID.recordName)")
} else {
println("\(error.localizedDescription)")
}
})
}
Terminal: Couldn't renew our secure session
I put an accountStatusWithCompletionHandler call outside of fetchUserRecordIDWithCompletionHandler, that returned CKAccountStatus.Available.
You cannot detect internet connectivity with CloudKit. It will only give you an error when there is no connectivity. If you do want to test for internet connectivity, then you could use the famous Reachability class like this: How to check for an active Internet connection on iOS or OSX?
If you want to detect changes to the iCloud account, then you can add the following code to your AppDelegate application didFinishLaunchingWithOptions:
var localeChangeObserver = NSNotificationCenter.defaultCenter().addObserverForName(NSUbiquityIdentityDidChangeNotification, object: nil, queue: NSOperationQueue.mainQueue()) { _ in
println("The user’s iCloud login changed: should refresh all user data.")
}
If you then want to fetch the user id, you have to do a container.requestApplicationPermission to see if you are allowed to query an then a container.fetchUserRecordIDWithCompletionHandler. Bit this requires internet connection. You could cache it on the device together with the detection code above to get the correct status.
I came across to this code, comparing recently and previous logged in user's token, and if the same, use the previously downloaded userRecordID. The only problem that in some cases on my iPad ubiquityIdentityToken method returns nil even dow I am logged in, strange.
class func checkUser() {
let ubiquityIdentityToken = NSFileManager.defaultManager().ubiquityIdentityToken
let status = Utility.status()
let prevUbiquityIdentityToken = status.objectForKey("ubiquityIdentityToken")
if ubiquityIdentityToken != nil && ubiquityIdentityToken!.isEqual(prevUbiquityIdentityToken) {
} else if ubiquityIdentityToken != nil && !ubiquityIdentityToken!.isEqual(prevUbiquityIdentityToken) {
status.setObject(ubiquityIdentityToken!, forKey: "ubiquityIdentityToken")
Utility.saveStatus(status)
let defaultContainer = CKContainer.defaultContainer()
let publicDatabase = defaultContainer.publicCloudDatabase
defaultContainer.fetchUserRecordIDWithCompletionHandler({ userRecordID, error in
if error == nil {
//do some stuff
})
} else {
println("\(error.localizedDescription)")
}
})
} else {
//do some stuff
status.removeObjectForKey("ubiquityIdentityToken")
Utility.saveStatus(status)
}
}

Resources