iOS Contacts - save a single contact without permissions (or permissions UI) - ios

CNAuthorizationStatus and the related documentation seems to suggest that you need permission to read or save to the CNContactStore. (And I've read most of the CNContact-based questions, and they are pretty consistent on that topic).
But I found an app that has a "Save Contact" button, and displays a contact in what looks like CNContactViewController, and when I pressed save, the app did save to contacts, but without any permissions dialog (and I never gave it permissions).
I uninstalled, re-installed and saved contact again, to confirm.
Has anyone done this before? I was on iOS 11.4.1.

I wrote an app that presents the Contact View for a new contact, and saves it to Contacts without:
requesting permission
using a purpose string NSContactsUsageDescription
The has been published in the app store for sometime now, as "DropCard".
The app also uses CNContactPickerViewController to select a single contact from the store, which interestingly says this:
The app using contact picker view does not need access to the user’s contacts and the user will not be prompted for “grant permission” access. The app has access only to the user’s final selection.
I conclude that similar-and-not-documented behavior is allowed for the creation of a single contact.
NOTE: This behavior does not allow a rogue app to programmatically jam large amounts of trash data into the Contacts store, because you still need the user to click on a button to save each new contact.
Here's the code I use for that portion
let contact = CNMutableContact()
let saveContactVC = CNContactViewController(forNewContact: contact)
saveContactVC.contactStore = CNContactStore()
saveContactVC.delegate = <your delegate here> as? CNContactViewControllerDelegate
saveContactVC.allowsActions = false
let navigationController = UINavigationController(rootViewController: saveContactVC)
root.present(navigationController, animated: false)
// NOTE: app *will* use right->left slide-over annimation...
// then the 'animated: false' supresses the NavUI's top->new VC animation.

Related

Posting to correct Instagram Account with UIActivityViewController

I am using UIActivityViewController to post images to Instagram app from MY app.
Please note my app does not use Instagram API or log in to users' Instagram Account.
let sharingImage = button.backgroundImage(for: [])
let avc = UIActivityViewController(activityItems: [sharingImage as AnyObject], applicationActivities: nil)
avc.excludedActivityTypes = [.addToReadingList,.airDrop,.assignToContact,.copyToPasteboard,.openInIBooks,.postToFacebook,.postToFlickr,.postToTencentWeibo,.postToTwitter,.postToVimeo,.postToWeibo,.saveToCameraRoll,.message,.mail,.print]
if let wPPC = avc.popoverPresentationController {
wPPC.sourceView = followUsButton
}
self.present(avc, animated: true, completion: nil)
I am logged into my Instagram App with multiple accounts. Upon share from MY app, Instagram tries to post to the account 'A' which is currently logged in (inside the Instagram app). This makes sense.
However, if I now switch to the Instagram app and switch to account 'B' inside it, go back to MY app and then try to share again, it continues to try to post to Account 'A'.
The only way to fix it, is to kill MY app and start it again and then it loads the correct currently logged in account 'B'.
Is there a way to programmatically reload the correct Insta account while sharing?
This is only a workaround however might be your only choice at the moment as you see that even native Photos has the same issue so it is rather down to Apple to fix it.
In your application's Info.plist, add a boolean key UIApplicationExitsOnSuspend with the value YES. See the Information Property List Key Reference for more information.
This way the app is getting terminated when enters a background state and once you go back to it it will get reloaded. The user might not notice the difference.
Perhaps before killing the app you could add some interface state saving function in:
optional func applicationWillTerminate(_ application: UIApplication)
I don't know how your app is laid out but you could create a singleton class which could be implementing Codable and keep tracking all the app state variables which would have a save and load function. Saving would be triggered upon termination and loading when app is launching.
I hope it will help in some way.
EDIT1: Should work in iOS 13
Below this code should work and terminate your app however it is not recommended and you might face an issue when uploading to AppStore. I guess you can challenge the rejection with the Apple review team by explaining that they have a bug in the SDK and point them to the problem.
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
exit(0)
}
}
Short answer, I doubt.
UIActivityViewController doesn't give you control over the user's login status (which is why it's interesting to use). IMO, that's a bug on Apple side. So, unless there's a secret way to clear the authorisation tokens that the iOS runtime has stored within your app memory, I don't see how you could possibly achieve what you want.
Plus, if Photos app has the same behaviour, that's not a good sign...
Just in case, when you say that the problem occurs when switching accounts, do you mean
In MY app, you immediately try to post from the same ViewController?
You move to a parent View (hence destroying the old one)back , then to the same view as 1/?
Do you have the same result in both case? I am asking because when instantiating a new UIActivityViewController in a new view, the runtime might fetch the new user login profile, while if you instantiate it from the same view that was used to post from the old account, it might not do so (hence it'll use the old login)
This is iOS issue not specific to your app.

check app settings using userDefaults in iOS using Swift

How do I check what the user sets app settings to? I think I'm supposed to be able to use UserDefaults to do this. I particularly want to check whether the user has allowed the app to access Contacts. I know how to get the setting if I knew the key. I would like to be able to access all the settings that UserDefaults have for the app. I am using Swift to create an iOS app.
You are misunderstanding what the UserDefaults class does. It has no knowledge of the user's settings. It's used for you to save a user's settings (from within your app) persistently.
As for how to access that kind of information. You have to use each of the APIs to check for permissions. For example, access to the GPS requires you to use LocationManager API and check the permission there.
To check if a user has given access to Contacts you have to use the Contacts API (link here)
More specifically this method:
class func authorizationStatus(for entityType: CNEntityType) -> CNAuthorizationStatus
EDIT:
You should really read on what the UserDefaults class is for. (link here)
You can't use UserDefaults to check whether the user has allowed the app to access Contacts. Try the following code.
let status = CNContactStore.authorizationStatus(for: CNEntityType.contacts)
switch (status) {
// Not determined or restricted (e.g.Parent control)
case CNAuthorizationStatus.notDetermined,CNAuthorizationStatus.restricted:
// Denied
case CNAuthorizationStatus.denied:
// Allowed
case CNAuthorizationStatus.authorized:
}

How to open specific contact's chat screen in WhatsApp from our app?

I wanted to integrate below functionality:
I am passing one contact number of a user. If that contact number already exists, directly opens that user's chat screen when I press on WhatsApp button in my app.
If that contact does not exist in the address book, then first, store this contact in the address book and then open that contact's chat screen in WhatsApp (with refreshing contacts so I will get the name of that person on WhatsApp chat screen).
I have done below task:
If contact does not exist, then it first stored in the address book and then move to WhatsApp. If I press the WhatsApp button again for the second time, then it checks that contact if it exists or not. If it's already saved, then fetch its record identifier and passed with WhatsApp URL scheme.
The main problem is that it just moves to WhatsApp's contact list, but does not open specific chat screen of the user.
Note: This thing works perfectly in Android, so I hope that it's also possible to integrate into iOS/Swift app.
Check out whats app Custom URL Scheme
https://www.whatsapp.com/faq/en/iphone/23559013
There is no URL Scheme registered for specific chat screen of user.
Simply Append with ABID with your whatsapp url scheme and call this its worked.
ABID stands for the Address book Record ID,the code below works to get the AB Record ID. It is sensitive to the use of delimeters in the URL itself.
To send a note to a specific user use this - urlstring format: whatsapp://send?abid=12&text=Hello%20World - note the use of & to mark the second parameter.
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
ARecordID = (ABRecordID)ABRecordGetRecordID(person);
....
whatsapp_string = [NSString stringWithFormat:#"whatsapp://send?abid=%d&text=%#;",ARecordID, "hello"];
....
}

iOS How should I open phonebook through coding

I am doing one project in that I am sending messages to multiple user.
When I am composing message I took one textfield for enter contact. When I click on contact textfield I want to open phone contact (like In Phone default compose message view how the all contacts appears when user click on "To") view.
In Android development we can open the phone contacts bye using "contact intent" I want to create like the same.
By using ABAddressBook I am able to fetch all contacts. But I dont want to create custom phonebook contact. So please help me that is there any default method to get default phone contacts controller in iOS.
For example how we directly open the setting page by using
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"prefs://"]];
this . I want the something like this to open the phone contact and once i finished any action(i.e selected any contact number) then it will get back to my app
Use the ABPeoplePickerNavigationController: https://developer.apple.com/library/ios/documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/UI_Controllers.html#//apple_ref/doc/uid/TP40007744-CH5-SW1

application would like to Access the Microphone ios alert [duplicate]

Anyway to custom permission alert view like: Contacts, Photo Album, Push Notifications... before they get access, they will pop up an alert view like this:
How to custom Contacts, photo album, push notifications alert view text?
UPdate:
See the update image above, translate into english:
"To seek for your family and friends, Path needs to transfer your
contacts to our server"
And click OK to get contacts access without any other access permission alert view pops up.
Under iOS 6 and above, these can be setup to show specific messages. Edit your Info.plist by adding a few new entries. The keys all begin with "Privacy - " (the raw keys are NSxxxUsageDescription where xxx is Contacts, Locations, Reminders, PhotoLibrary, or Calendards). The value is the text you wish to display to the user.

Resources