CNContactStore execute fails - swift

I am working out how to use the Contacts framework, however some fairly simple code to create a contact is failing with an unexpected result. This is my code:
let Store = CNContactStore()
Store.requestAccess(for: .contacts, completionHandler:{ success, error in
if success {
let Contact = CNMutableContact()
Contact.givenName = "Dave"
Contact.familyName = "Nottage"
let SaveRequest = CNSaveRequest()
SaveRequest.add(Contact, toContainerWithIdentifier: nil)
do {
try Store.execute(SaveRequest)
print("Success")
}
catch let error as NSError {
print(error.localizedDescription)
}
} else {
print("No access")
}
})
..and this is the result:
2019-02-22 10:30:56.050344+1030 ContactsTest[30329:25254955] [default] Unable to load Info.plist exceptions (eGPUOverrides)
2019-02-22 10:30:57.973724+1030 ContactsTest[30329:25254955] Could not get real path for Address Book lock folder: open() for F_GETPATH failed.
2019-02-22 10:30:57.973954+1030 ContactsTest[30329:25254955] Unable to open file lock: <ABProcessSharedLock: 0x600001752ac0: name=(null), lockFilePath=(null), localLock=<NSRecursiveLock: 0x600002914a80>{recursion count = 0, name = nil}, fileDescriptor=-1> Error Domain=NSPOSIXErrorDomain Code=14 "Bad address" UserInfo={ABFileDescriptor=-1}
The operation couldn’t be completed. (Foundation._GenericObjCError error 0.)
Any ideas on what might be causing this?
Edit: Note also that this is being compiled for macOS 10.14 SDK, and is running on macOS 10.14.3

The answer is to check the Contacts checkbox of App Data in the App Sandbox section in Capabilities and turn on the switch for App Sandbox.

Make sure you added key NSContactsUsageDescription in Info.plist.
Please refer to link.
Important
An iOS app linked on or after iOS 10.0 must include in its Info.plist
file the usage description keys for the types of data it needs to
access or it will crash. To access Contacts data specifically, it must
include NSContactsUsageDescription.

Related

Swift: "NSCocoaErrorDomain Code=134092" when executing CNSaveRequest of Contact Store

I'm writing a command line program with Swift Package Manager that uses Contacts API to automatically add phonetic names for the contacts. However, I found I was unable to do so for contacts that has notes. First, when I was trying to enumerate the contacts, there is a strange error output:
2023-01-22 18:58:36.085525+0800 PhoneticNames[18591:98356] [core] Attempted to register account monitor for types client is not authorized to access: {(
"com.apple.account.CardDAV",
"com.apple.account.Exchange",
"com.apple.account.LDAP"
)}
2023-01-22 18:58:36.085580+0800 PhoneticNames[18591:98356] [accounts] CNAccountCollectionUpdateWatcher 0x6000003ccc40: Store registration failed: Error Domain=com.apple.accounts Code=7 "(null)"
2023-01-22 18:58:36.085606+0800 PhoneticNames[18591:98356] [accounts] CNAccountCollectionUpdateWatcher 0x6000003ccc40: Update event received, but store registration failed. This event will be handled, but the behavior is undefined.
2023-01-22 18:58:36.136236+0800 PhoneticNames[18591:98344] [api] Attempt to read notes by an unentitled app
According to this document, I need to add the notes entitlement only if I was requesting the note field with CNContactNoteKey. However, I was not requesting it and I still get that "Attempt to read notes by an unentitled app" error.
Here is my code for enumerating the contacts:
let keys: [CNKeyDescriptor] = [CNContactFormatter.descriptorForRequiredKeys(for: .fullName),
CNContactFormatter.descriptorForRequiredKeys(for: .phoneticFullName)]
let fetchRequest = CNContactFetchRequest(keysToFetch: keys as [CNKeyDescriptor])
fetchRequest.mutableObjects = true
do {
try store.enumerateContacts(with: fetchRequest) { (contact, stop) in
contacts.append(contact.mutableCopy() as! CNMutableContact)
}
} catch {
print("unable to list contacts. \(error)")
}
And this is how I update the contacts later:
let saveRequest = CNSaveRequest()
contact.phoneticFamilyName = phoneticFamilyName
contact.phoneticMiddleName = phoneticMiddleName
contact.phoneticGivenName = phoneticGivenName
saveRequest.update(contact)
do {
try store.execute(saveRequest)
} catch {
print("Fail to execute store request: \(error)")
}
This code works as expected for contacts without the note field. But for contact with a non-empty note field, the saveRequest fails and outputs the following error:
2023-01-22 18:58:36.197026+0800 PhoneticNames[18591:98344] [error] error: Unhandled error occurred during faulting: Error Domain=NSCocoaErrorDomain Code=134092 "(null)" ({
})
CoreData: error: Unhandled error occurred during faulting: Error Domain=NSCocoaErrorDomain Code=134092 "(null)" ({
})
I am using Swift 5.7, Xcode 14.2, macOS 13.1. I looked for all the documents but couldn't find anything about NSCocoaErrorDomain Code 134092.
I shouldn't receive the error "Attempt to read notes by an unentitled app" when I am not requesting notes. And I should be able to successfully execute the saveRequest that doesn't modify the note field. Does anyone knows how these error comes?

Firebase Phone Authentication works on Simulator but not phone

I finally decided its time for testflight with my app. Authentication works perfectly in the simulator. I've tried it with test numbers (works great), I've tried it with my phone (sends verification code), and I've tried it with my parents phone (a device that has never been set up with my firebase) and it worked great.
As soon as I set it up on my device and tried to authenticate the same way, I encountered an error
here is the very simple code I took straight from firebase docs
public func startAuth(phoneNumber: String, completion: #escaping (Bool) -> Void) {
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { [weak self] verificationId, error in
guard error == nil else {
print("error verifying phone numer, Error: \n\(error!)")
completion(false)
return
}
self?.verificationId = verificationId
completion(true)
}
}
When running in the simulator, it works great, when running on my phone, I get this error:
error verifying phone numer, Error:
Error Domain=FIRAuthErrorDomain Code=17999 "An internal error has occurred, print and inspect the error details for more information." UserInfo={FIRAuthErrorUserInfoNameKey=ERROR_INTERNAL_ERROR, NSLocalizedDescription=An internal error has occurred, print and inspect the error details for more information., NSUnderlyingError=0x283f43c30 {Error Domain=FIRAuthInternalErrorDomain Code=3 "(null)" UserInfo={NSUnderlyingError=0x283f9bae0 {Error Domain=com.google.HTTPStatus Code=503 "(null)" UserInfo={data={length = 207, bytes = 0x7b0a2020 22657272 6f72223a 207b0a20 ... 5d0a2020 7d0a7d0a }, data_content_type=application/json; charset=UTF-8}}, FIRAuthErrorUserInfoDeserializedResponseKey={
code = 503;
errors = (
{
domain = global;
message = "Error code: 33";
reason = backendError;
}
);
message = "Error code: 33";
}}}}
I've tried adding the firebase auth SDK: https://github.com/firebase/firebase-ios-sdk to the project and I get an error in a random file that says "redfinition of module 'Firebase'" and other stack overflow posts say to just delete the SDK and it'll solve your issue.
I'm really confused, why does it only work in the simulator and not my device?
Is the SDK really the solution and I need to find another way around the redefinition issue?
Thanks for your help in advance!

requestApplicationPermission userDiscoverability failed in Mac Catalyst

I have ios app using requestApplicationPermission userDiscoverability. Today, I add Mac Catalyst support, but failed: "requestApplicationPermission(.userDiscoverability) failed, error: CloudKit access was denied by user settings".
container.requestApplicationPermission(.userDiscoverability) { [weak self] (status, error) in
guard let self = self else { return }
DispatchQueue.main.async {
if let error = error {
foolPrint("requestApplicationPermission(.userDiscoverability) failed, error: \(error.localizedDescription)")
}
}
}
And I cannot find settings about userDiscoverability in mac settings, where is it?
This iCloud user guide shows how to change these settings:
On iCloud.com, go to Account Settings, then click Manage Apps That Can Look You Up in the Advanced section.
To prevent an app from showing your name and email address to other users, deselect the app’s checkbox in the list.

CloudKit - "Invalid bundle ID for container"

I've just create a project in Xcode 9 beta 6 and add this code:
let privateDB = CKContainer.default().privateCloudDatabase
let greatID = CKRecordID(recordName: "GreatPlace")
let place = CKRecord(recordType: "Place", recordID: greatID)
privateDB.save(place) { (record, error) in
if error != nil {
let er = (error as! CKError).errorUserInfo
print("Error: \n")
print("CKErrorDescription: \(er["CKErrorDescription"]!)\n")
print("ContainerID: \(er["ContainerID"]!)\n")
print("NSDebugDescription: \(er["NSDebugDescription"]!)\n")
print("NSUnderlyingError: \(er["NSUnderlyingError"]!)\n")
print("NSLocalizedDescription: \(er["NSLocalizedDescription"]!)\n")
print("ServerErrorDescription: \(er["ServerErrorDescription"]!)\n")
}
if record != nil {
print("record: \(record!)")
}
}
and add this capabilities:
and when I run the code I receive this error message:
What I am doing wrong ?
There was a bug causing some associations to be missed. That bug has been fixed and we automatically fixed the container/app associations that were broken during that time.
If for some reason you still need to redo an association you can either use the Capabilities pane in Xcode or use developer.apple.com -> Certificates, Identifiers & Profiles -> App IDs -> pick the ID -> Edit -> Edit under iCloud -> check the box for the container to disassociate, save, then re-associate.
If you're still stuck please email cloudkit[at]apple.com
My friend and I are having the same issue. We made 2 different projects and both of them had the same error message "Invalid bundle ID for container" which is CKError case 10 .
We are calling our fetch function to get the default "Users" record in the viewDidLoad.
func fetchWorkoutCompleted(completion: #escaping (Error?) -> Void = { _ in }) {
cloudKitManager.fetchRecord(ofType: "Users", sortDescriptors: nil) { (records, error) in
if let error = error {
print(error.localizedDescription)
completion(error)
return
}
guard let records = records else { completion(nil); return }
completion(nil)
}
}
Using Xamarin.IOS, I had to select manual provisioning rather than automatic provisioning in the info.plist file.
Had the same issue. what worked for me was changing the iCloud group name.
Before it was something like this: iCloud.com.companyName.appName.randomString
After changing to: iCloud.com.companyName.randomString it started working and synchronising.
If after adding the new container it's red press the refresh button(from under the groups) and try a clean install on your phone and it should work
Thanks to Dave Browning, this is based on his answer.
Following worked for me:
Check the container id
Check the container id used for initialisation of CKContainer
Note: If you are using NSPersistentCloudKitContainer we wouldn't be using the container id directly would be picked automatically from the entitlements file.
Try to disable and enable iCloud on the App ID
Disable and Enable iCloud on App ID
Go to https://developer.apple.com and sign in
Select Certificates, Identifiers & Profiles
Select Identifiers (App IDs)
Edit App ID for the app
Uncheck iCloud
Save
Check iCloud
Quit Xcode and Clear DerivedData
Run app

Connecting to VPN with Swift 3

I'm trying to connect to a VPN in an iOS app. What I already know is the VPN type (L2TP over IPSec), account name, password and shared secret. The connection works through Mac's Network settings. Although, it seems a little more complicated, when you have to use this info in code.
First, I have imported the necessary library.
import NetworkExtension
Then, I'm trying to load preferences and in case of error, I'm using my own and save them. Looks like this:
NEVPNManager.shared().loadFromPreferences { error in
// config
NEVPNManager.shared().saveToPreferences { error in
if (error == nil) {
do {
try NEVPNManager.shared().connection.startVPNTunnel()
} catch {
print("Couldn't connect")
}
} else {
print("NEVPNManager.saveToPreferencesWithCompletionHandler failed: \(error!.localizedDescription)")
}
}
}
Where you can see the "// config", my data should be passed. I'm not 100% sure, if I'm doing it right.
There's a constant let p = NEVPNProtocolIPSec() where I'm placing my data. It's like p.username = "smth".
The question is: which fields of p should be filled? Where do I put the shared secret?
--- UPDATE ---
I'm always getting the error:
NEVPNManager.saveToPreferencesWithCompletionHandler failed: The operation couldn’t be completed. (NEVPNErrorDomain error 4.)
I can't find anything specific about that.
During the config, fields .sharedSecretReference and .passwordReference require the Data? object. I'm getting it by using keychain.get("passref")?.data(using: .utf8, allowLossyConversion: true) preceded by
let keychain: KeychainSwift! = KeychainSwift()
keychain.set("<my_password>", forKey: "passref")
(class KeychainSwift comes from here)
Where am I making a mistake?