Pop for request access to contacts not show ios 9 - ios

I'm fetching contacts from address book but popup not show to ask permission to access contacts. it automatically denied but when i try same code in a demo then it run properly but it ddi not run in my app.
I have read many articles but i did not get any solution. Is i'm missing something in plist or settings.
CNContactStore * contactStore = [[CNContactStore alloc]init];
if ([CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts] == CNAuthorizationStatusNotDetermined) {
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * __nullable error) {
if (granted==YES)
{
}
else
{
NSLog(#"Error");
}
}];
}
or second methods
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (error)
{
NSLog(#"error %#", error);
}
else if (granted)
{
}
CFRelease(addressBook);
});
}

I also had this issue today, and I deleted some keys from Info.plist:
<key>CFBundleDisplayName</key>
<string></string>
<key>LSApplicationCategoryType</key>
<dict/>
<key>CFBundleGetInfoString</key>
<string></string>
It works now. wired case.

Entering my application's name in the info.plist "Bundle display name" key allowed my app to show a request for access to my contacts.

I had the same issue. Cody's answer led me to try this which worked for me.
In your Info.plist, for the key "Bundle display name", make sure it's not an empty string. This name is used when prompting for the contacts permission.

Related

create new group with contacts framework, CNErrorDomain Code = 2

i try to create and save a group with the Contacts Framework.
First the user authorize the App for contacts access.
A viewcontroller is presented and with a + button user shows an alertview with textfield.
The user types the group name he wants and click to button of the alertview (save).
This is the code for saving the new group. The group name is available but it is not possible to save this group anyway:
CNContactStore *contactStore = [CNContactStore new];
[contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *error){
if (granted) {
CNMutableGroup *newGroup = [CNMutableGroup new];
CNSaveRequest *saveRequest = [CNSaveRequest new];
[newGroup setName:groupName];
//when saving to container with identifier nil, we get this error:
//Error Domain=CNErrorDomain Code=2 "(null)" UserInfo={CNInvalidRecords=(
//"<CNMutableGroup: 0x10a059f20: identifier=2F4981B9-8A47-45A4-8841-1FA5A09584A4:ABGroup, name=gghh>"
[saveRequest addGroup:newGroup toContainerWithIdentifier:nil];
[contactStore executeSaveRequest:saveRequest error:&error];
if (error){
//error saving group
//NSLog(#"error message: %#",error);
} else {
//if no errors, reload tableview
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}
}];
Error Domain=CNErrorDomain Code=2 "(null)" UserInfo={CNInvalidRecords=(
"<CNMutableGroup: 0x14fb3e5e0: identifier=8E490585-1223-407E-B353-0D25609B05AB:ABGroup, name=jddjd>"
)}
The next strange thing is: why is the save request trying to save this group
with identifier :ABGroup at the end?
The Error contains a info about CNInvalidRecords.
I am only using the Contacts Framework.
Why is this happening?
Any solutions for that?
It worked fine for me, with essentially the same code.
CNMutableGroup *newGroup = [CNMutableGroup new];
CNSaveRequest *saveRequest = [CNSaveRequest new];
[newGroup setName:self.groupName];
[saveRequest addGroup:newGroup toContainerWithIdentifier:nil];
[contactStore executeSaveRequest:saveRequest error:&error];
And created a new group

setImageData fails in iOS 8.3

I am using setImageData to delete a photo in the following way :
[asset setImageData:nil metadata:nil completionBlock:^(NSURL *assetURL, NSError *error)
{
// Do something
}];
This code was working perfectly fine in iOS 8.2 and earlier versions.
But, in 8.3 it gives the error :
#"Error Domain=ALAssetsLibraryErrorDomain Code=-3311 \"User denied access\" UserInfo=0x175061ac0 {NSLocalizedFailureReason=The user has denied the application access to their media., NSLocalizedDescription=User denied access, NSUnderlyingError=0x17025d700 \"The operation couldn’t be completed. (ALAssetsLibraryErrorDomain error -3311.)\”}"
I tried replacing the image data and metadata fields with some valid image data instead of “nil”. Still it gives the same error!!
Is this some bug in iOS 8.3? Is there any workaround?
Thanks in anticipation.
Another important information :
[PHPhotoLibrary authorizationStatus] returns "PHAuthorizationStatusAuthorized".
[ALAssetsLibrary authorizationStatus] also returns "ALAuthorizationStatusAuthorized".
As far as I know, the setImageData method was never intended to be used as a method for deleting assets. It is possible that on iOS 8.3 Apple patched things up so this no longer works.
I recommend that you look into using the Photos framework which includes a dedicated method for deleting assets.
Here's an example:
-(void)deleteAssetWithURL:(NSString*)assetURLString
{
NSURL *assetURL = [NSURL URLWithString:assetURLString];
if (assetURL == nil)
{
return;
}
PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:#[assetURL] options:nil];
if (result.count > 0)
{
PHAsset *phAsset = result.firstObject;
if ((phAsset != nil) && ([phAsset canPerformEditOperation:PHAssetEditOperationDelete]))
{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^
{
[PHAssetChangeRequest deleteAssets:#[phAsset]];
}
completionHandler:^(BOOL success, NSError *error)
{
if ((!success) && (error != nil))
{
NSLog(#"Error deleting asset: %#", [error description]);
}
}];
}
}
}
When using the Photos framework, don't forget to link Photos.framework in your target and also import the header in your source file: #import <Photos/Photos.h>
I have a similar problem, and haven't been able to resolve it either. I think its a bug in 8.3 with the AssetsLibrary, and would suggest you submit a bug report to Apple as I have:
Can't edit photo metadata using AssetsLibrary in iOS 8.3 (worked in 8.2)
The user has denied the application access to their media
This explains why you have the error. As far as the system is concerned you don't have access to the photo library.
You need to look at checking the authorization status and requesting if needed as show in the Apple Doc's
You need something like:
if([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatus.PHAuthorizationStatusAuthorized){
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status)
{
if (status != PHAuthorizationStatus.PHAuthorizationStatusAuthorized)
{
//Fail
}
else
{
//SetImageData
}
}
}

objective-c Completion Block issue

I am trying to get a JSON (NSString *) of the address book , in async task , however I want it to be asynchronously and with a completion block .
I have managed to retrieve that easy without the completion block , however when I am adding the completion block I have the following compiler error :
Incompatible block pointer types passing NSString *(^)(bool, CFErrorRef)' to parameter of type 'ABAddressBookRequestAccessCompletionHandler' (aka 'void (^)(bool, CFErrorRef)')
here is my code
+ (NSString *) getAddressBook:(id (^)())block {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied)
{
// if you got here, user had previously denied/revoked permission for your
// app to access the contacts, and all you can do is handle this gracefully,
// perhaps telling the user that they have to go to settings to grant access
// to contacts
[[[UIAlertView alloc] initWithTitle:nil message:#"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
return nil;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (error)
{
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
if (addressBook) CFRelease(addressBook);
return nil;
}
if (status == kABAuthorizationStatusNotDetermined)
{
// present the user the UI that requests permission to contacts ...
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) -> THE ERROR OCCURS HERE !
{...
I think the problem is within my completion blocks , but I can't find some good example/tutorial for my specific issue I would be really glad if some 1 could help me please.
Your problem is that you are declaring getAddressBook like this(if we strip block)
-(id)block
And you are trying to pass it as a function of type:
-(void)block:(BOOL)aBool error:(CFErrorRef*)error
Blocks are quite hard to get used with syntax(which is improved in swift) however I'm always refering to this site when not sure:
block syntax reference
UPDATE:
You have to actually wait for your async method finish. You may also refer to official documentation
+ (void) getAddressBook:((^)(NSString* result))block {
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied)
{
// if you got here, user had previously denied/revoked permission for your
// app to access the contacts, and all you can do is handle this gracefully,
// perhaps telling the user that they have to go to settings to grant access
// to contacts
[[[UIAlertView alloc] initWithTitle:nil message:#"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
block(nil);
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (error)
{
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
if (addressBook) CFRelease(addressBook);
block(nil);
}
if (status == kABAuthorizationStatusNotDetermined)
{
// present the user the UI that requests permission to contacts ...
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) -> THE ERROR OCCURS HERE !
{
NSString* result = whatever
block(result);
});
}
}
And use it like this:
[YourClass getAddressBook:^(NSString* result)
{
//now you really have result
}];

App not asking for Contact access permission on iOS 6

I am using below Code, My application don't ask permission on iOS 6 while on iOS 7 and above version it ask for Contact permission access. On iOS 6 it doesn't show app in privacy setting as well. I have read some other thread but not found any solutions.
App crashed in iOS 6 when user changes Contacts access permissions
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0")) {
__block CDNDeviceContact *controller = self;
// Request authorization to Address Book
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef,
^(bool granted, CFErrorRef error) {
if (granted)
[controller loadContacts];
else [controller doAlertForContact];
});
} else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
// The user has previously given access, add the contact
[self loadContacts];
} else {
[controller doAlertForContact];
}
if (addressBookRef) CFRelease(addressBookRef);
}
If the user has previously been presented with the request to get permission, it will not show again. According to the documentation,
The user is only asked for permission the first time you request access. Later calls use the permission granted by the user.
If testing in the simulator, I recommend that you go to iOS Simulator -> Reset Content and Settings so that you are able to simulate the event.
You don't need SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO and you also don't need to create an ABAddressBookRef.
For me, this is works like a charm:
if (ABAddressBookGetAuthorizationStatus) {
switch (ABAddressBookGetAuthorizationStatus()) {
case kABAuthorizationStatusNotDetermined:{
ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {
self.addContactButton.enabled = granted;
if (granted) {
// granted
} else {
// User denied access
}});
} break;
case kABAuthorizationStatusDenied: break;
case kABAuthorizationStatusAuthorized: break;
default: break;
}
}

ABAddressBookCopyArrayOfAllPeople wrong on device - right on simulator

I have the following code:
NSMutableArray *contacts = [[NSMutableArray alloc]init];
CFErrorRef *error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
if (error)
}
NSArray *arrayOfPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
It works on the simulator and gives me the expected results - however on the device the number of contacts is 0 and there is no error (the app strangely does not ask me for permissions to access the address book - I even deleted and reinstalled the app)
Any Ideas ?
Thanks in advance
On ios 6 you need get access to the Address Book.
Call ABAddressBookRequestAccessWithCompletion() to get the permission.
see this and AddressHelper
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (error) {
NSLog(#"error %#", error);
}else if (granted){
// Do what you want with the Address Book
}else{
NSLog(#"permission denied");
}
CFRelease(addressBook);
});

Resources