Device not working with Firebase Authentication Phone Number - ios

I have an iPhone that I'm trying to use with firebase authentication using phone numbers.
The project works and the emulator + device (without sim card) works using that phone number of the device that doesn't work (receives sms). But when I try to "login" on the device (with sim) I keep getting nil from verifyPhoneNumber. Is there something I'm missing that has to be active on the device?
This is the code that I'm trying to call with the text field as +1**********, along with FirebaseApp.configure() in the AppDelegate
PhoneAuthProvider.provider().verifyPhoneNumber(phoneTextField.text!, uiDelegate: nil) { (veri, error) in
if error != nil {
print(veri)
} else {
print(error)
}
}

There is likely an error, but it's not surfacing because the if statement is backwards. Instead, it should be
PhoneAuthProvider.provider().verifyPhoneNumber(phoneTextField.text!, uiDelegate: nil) { (veri, error) in
if error != nil {
print(error)
} else {
print(veri)
}
}
This will then print error instead of veri. It's likely printing nil because veri has no value if there's an error.

Related

"Cannot Parse Response" error when logging in from certain countries - MongoDB Atlas Device Sync (prev. Realm Sync)

I'm using MongoDB's Atlas Device Sync (until recently it was called Realm Sync) to handle login for my iOS app, coded in Swift.
I am UK based, and the app works fine for users in the UK. However, I recently sent the app to contacts in Eastern Europe (Poland, Belarus, potentially other countries as well. One person also tried logging in using a French VPN apparently) and they've all received the same error when creating an account or logging in with an already created account.
The localised description of this error is "cannot parse response".
Unfortunately I am based in the UK so I can't replicate it on my own device. However, I know that the error when creating an account is being thrown from the below code:
app.emailPasswordAuth.registerUser(email: email!, password: password!, completion: { [weak self] (error) in
DispatchQueue.main.async {
guard error == nil else {
self!.signUpFailed(with: error!)
return
}
self!.signIn(with: self!.email!, and: self!.password!)
}
})
And I know that the error when logging in to an already created account is being thrown from the below code:
app.login(credentials: Credentials.emailPassword(email: email, password: password)) { [weak self] (result) in
DispatchQueue.main.async {
switch result {
case .failure(let error):
self!.signInFailed(with: error)
return
case .success(let user):
self!.continueLoggingIn()
}
}
}
I'm at a bit of a loss here. I have no idea why the response can be parsed in the UK but not other countries. I assume it's an issue with Mongo/Realm but I could be wrong. If anyone can shed any light it would be greatly appreciated.

Xcode HomeKit add device to Home app using X-HM: or code pin

I learn the Homekit to integrate my IOT device.
let payload = HMAccessorySetupPayload.init(url: URL.init(string: "X-HM://XXXXXXXXX"))
let request = HMAccessorySetupRequest()
request.payload = payload
let setupManager = HMAccessorySetupManager()
setupManager.performAccessorySetup(using: request) { (result, error) in
if (error != nil) {
print("Error from addAndSetupAccessories:", [error?.localizedDescription])
} else {
print("The accessory is added.")
}
}
The "X-HM" link is provided by OpenHab but it returned a error:
Failed to perform accessory setup using request: Error Domain=HMErrorDomain Code=17 "(null)"
I find other user say you need set the permission but I cannot set this in Entitlements file. It return error not find this.
“com.apple.developer.homekit.allow-setup-payload”
Question 1:
in the Homekit doc mean, the link must join "MFi Program"?
====
Question 2:
also, i have the pin code, Could i skip the input step in app setup?
i use the below code but this has not option to input the pin code, it need user to input using keyboard.
let setupManager = HMAccessorySetupManager()
setupManager.performAccessorySetup(using: HMAccessorySetupRequest()) { (result, error) in
if (error != nil) {
print("Error from addAndSetupAccessories:", [error?.localizedDescription])
} else {
print("The accessory is added.")
}
}

NEHotspotConfigurationManager getting this alert:"Unable to join the network<name of network>" while error is nil

So i am trying to monitor the connection status by closers :
func reconnect(success: #escaping () -> Void, failure: #escaping () -> Void) {
let manager = NEHotspotConfigurationManager.shared
let ssid = CameraManager.camera.uuid
let password = "password"
let isWEP = false
let hotspotConfiguration = NEHotspotConfiguration(ssid: ssid, passphrase: password, isWEP: isWEP)
hotspotConfiguration.joinOnce = true
manager.apply(hotspotConfiguration) { (error) in
if (error != nil) {
if let error = error {
switch error._code {
case 8:
print("internal error")
failure()
case 7:
NotificationCenter.default.post(name: Notification.Name(rawValue: "cancelFromHotSpot"), object: nil)
failure()
self.stopSession()
case 13:
success()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.startSession()
}
default:
break
}
}
if error == nil {
print("success connecting wifi")
success()
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.startSession()
}
}
}
}
Yet there is a scenario that i am getting this alert "Unable to join the network" while error is nil, any ideas?
I think this behavior is a iOS bug and we cannot avoid.
This problem was also discussed in Apple Developer Forum and answer of Apple staff was below
"I’ve got nothing to say here beyond what I said on 13 Feb. The fact that errors from the Wi-Fi subsystem don’t get reported via the completion handler is expected behaviour. If you don’t like that behavior — and, to be clear, I personally agree with you about that — the best way forward is to file a bug report requesting that it be changed. Please post your bug number, just for the record."
This was discussed here
So I do not have great ideas, unfortunately. All ideas I have are two below (these do not solve this problem perfectly.)
Wait for a bug fix in the future release.
Separate "Applying Configuration" code & Communication code like below.
#IBAction func setConfigurationButtonTapped(_ sender : Any) {
manager.apply(hotspotConfiguration) { (error) in
if(error != nil){
// Do error handling
}else{
// Wait a few seconds for the case of showing "Unable to join the..." dialog.
// Check reachability to the device because "error == nil" does not means success.
}
}
#IBAction func sendButtonTapped(_ sender : Any) {
self.startSession()
}
iOS 13 - Patch
I had the same problem, but I solved it by deleting first all the existing configuration entries:
NEHotspotConfigurationManager.shared.getConfiguredSSIDs { (wifiList) in
wifiList.forEach { NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: $0) }
// ... from here you can use your usual approach to autoconnect to your network
}
Maybe it's not always a possible solution since it's a bit drastic, but for me worked like a charm.
PS: I use this in an app that runs iOS 13. As far as I know should work also on iOS 11 and 12, but I didn't test it.
Remove hotspotConfiguration.joinOnce = true work for me

CloudKit: Get users firstname/surname

I'm trying to get the users first name using cloud kit however the following code is not getting the users first name and is leaving firstNameFromFunction variable empty. Does anyone know how to achieve this in iOS 10?
let container = CKContainer.default()
container.fetchUserRecordID { (recordId, error) in
if error != nil {
print("Handle error)")
}else{
self.container.discoverUserInfo(
withUserRecordID: recordId!, completionHandler: { (userInfo, error) in
if error != nil {
print("Handle error")
}else{
if let userInfo = userInfo {
print("givenName = \(userInfo.displayContact?.givenName)")
print("familyName = \(userInfo.displayContact?.familyName)")
firstNameFromFunction = userInfo.displayContact?.givenName
}else{
print("no user info")
}
}
})
}
}
the permission screen that comes up when asking for the first time, IMO, is very poorly worded. They need to change that. It says "Allow people using 'your app' to look you up by email? People who know your email address will be able to see that you use this app." This make NO sense. This has nothing to do with asking the user to get their iCloud first name, last name, email address.
Speaking of email address - this and the phone number from the lookupInfo property is missing - i.e. set to nil, even though those values are legit and correct. Filing a bug tonight.
First, you will need to request permission to access the user's information.
Then, you can use a CKDiscoverUserIdentitiesOperation. This is just like any other CKOperation (eg. the modify record operation). You just need to create a new operation with the useridentitylookupinfo. Then you will also need to create a completion block to handle the results.
Here is an example function I created:
func getUserName(withRecordID recordID: CKRecordID,
completion: #escaping (String) -> ()) {
if #available(iOS 10.0, *) {
let userInfo = CKUserIdentityLookupInfo(userRecordID: recordID)
let discoverOperation = CKDiscoverUserIdentitiesOperation(userIdentityLookupInfos: [userInfo])
discoverOperation.userIdentityDiscoveredBlock = { (userIdentity, userIdentityLookupInfo) in
let userName = "\((userIdentity.nameComponents?.givenName ?? "")) \((userIdentity.nameComponents?.familyName ?? ""))"
completion(userName)
}
discoverOperation.completionBlock = {
completion("")
}
CKContainer.default().add(discoverOperation)
} else {
// iOS 10 and below version of the code above,
// no longer works. So, we just return an empty string.
completion("")
}
}
First you need to ask the user for permission to be discovered.
Use CKContainer.default().requestApplicationPermission method passing .userDiscoverability on applicationPermission parameter.
The CKContainer.default().discoverUserInfo method is deprecated on iOS 10. Instead use CKContainer.default().discoverUserIdentity method.
Do something like:
CKContainer.default().requestApplicationPermission(.userDiscoverability) { (status, error) in
CKContainer.default().fetchUserRecordID { (record, error) in
CKContainer.default().discoverUserIdentity(withUserRecordID: record!, completionHandler: { (userIdentity, error) in
print("\(userIdentity?.nameComponents?.givenName)")
print("\(userIdentity?.nameComponents?.familyName)")
})
}
}

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