This question already has answers here:
Find Favorite contacts from the iOS Address Book API
(3 answers)
Closed 4 years ago.
My iOS application fetches contacts from device using code
[[CNContactStore new] requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError *error) {
if (granted) {
NSArray *keys = #[CNContactNamePrefixKey,
CNContactGivenNameKey,
CNContactMiddleNameKey,
CNContactFamilyNameKey,
// ...
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
for (CNContact *contact in cnContacts) {
// contacts fetching
}
}
}];
Has CNContact class some value means that contact is in favorites on device (in Phone application)? I didn't found such key in CNContact keys.
Or maybe predicate contains keys that I needs?
Filip Radelic answered same question:
Favorites are stored inside Phone.app, not inside the Address Book database itself. You can't access other app's sandbox on a non-jailbroken iPhone, so unfortunately the answer is no.
Also, it would be pretty bad for privacy if any app could see your favorite contacts. It's already bad that it can access entire address book without asking you.
Related
No matter what I try, iOS is telling me that I have 0 groups. I've tried both the ABGroup and CNGroup API. Nada. If I go into the Contacts app on my iPad and click on Groups, I see it listing five different groups (as expected). But both [CNContactStore groupsMatchingPredicate:error:] and ABAddressBookCopyArrayOfAllGroups() are giving me 0 element arrays back.
Here is my code for each:
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES) {
NSError *error;
NSArray *cnGroups = [store groupsMatchingPredicate:nil error:&error];
for( CNGroup *group in cnGroups ) {
AWLogInfo(#"JMS CN Group: %#", group.name);
}
}
}];
CFArrayRef allGroups = ABAddressBookCopyArrayOfAllGroups(addressBook);
for( int iGroup = 0; iGroup < CFArrayGetCount(allGroups); iGroup++ ) {
ABRecordRef groupRef = CFArrayGetValueAtIndex(allGroups, iGroup);
NSString *groupName = (__bridge_transfer NSString*)ABRecordCopyValue(groupRef, kABGroupNameProperty);
AWLogInfo(#"JMS Group %ld: %#", (long) iGroup, groupName);
}
(Note that I don't request AddressBook permission, because that's already being done elsewhere in my app. I am able to access contacts just fine -- in fact, right after this code snippet is some code that iterates through all of the contact records and it is no problem.)
What gives? What am I missing?
Edit: Note that I can see groups I create, I just can't see the groups created by other apps. I can see the contacts within those groups, but not the groups themselves. Is this expected behavior?
I was confusing groups with sources. If you list all sources, you'll get the stuff created by other apps.
That said, iOS seems to be pretty lousy about giving you a useful name for a source, so this still isn't really doing what I want.
Requirement: I am saving some contacts into the user's iPhone along with a picture (dimensions same as the device). I want this picture to be displayed ON FULLSCREEN whenever the contact calls on that device.
Noticed Example: Truecaller iOS app shows as Red image when the caller is Identified as Spam
Code: This is code I have used to save the contacts data. I am using Contacts.framework
CNMutableContact *newContact = [CNMutableContact new];
newContact.imageData = UIImagePNGRepresentation([UIImage imageNamed:#"blue_bg.png"]);
newContact.contactType = CNContactTypePerson;
newContact.givenName = user.firstName;
newContact.middleName = user.middleName;
newContact.familyName = user.lastName;
NSArray *numbers = [[NSArray alloc] initWithArray:#[[CNLabeledValue labeledValueWithLabel:#"Main" value:[CNPhoneNumber phoneNumberWithStringValue:user.mobileNumber.stringValue]]]];
newContact.phoneNumbers = numbers;
CNContactStore *store = [CNContactStore new];
CNSaveRequest *saveReq = [CNSaveRequest new];
[saveReq addContact:newContact toContainerWithIdentifier:nil];
NSError *error = nil;
[store executeSaveRequest:saveReq error:&error];
if (error) {
NSLog(#"Contact Save ERROR: %#", error.localizedDescription);
}
Current Scenario: I am getting this image in the iOS Contacts App but its not displayed when that user calls on the iPhone. How does Truecaller do it? What am I missing here?
If the image shows up in the Contacts App it should show up when you're getting called by that person.
I'm working on my app and at a certain point the user can convince their friends to download it. However, the ABAddressBook framework (link) has been deprecated with iOS 9, so I had to teach myself the newest Contacts framework (link).
However, I'm still facing issues. I have read the documentation up to this point:
NSArray *keysToFetch = #[CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey];
NSString *containerId = [self.CN_contacts defaultContainerIdentifier];
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
self.allContacts = [self.CN_contacts unifiedContactsMatchingPredicate:predicate keysToFetch:keysToFetch error:nil];
But I know that the block of code is missing the functionality of asking the user to grant access to their contacts.
Does anyone knows a way to ask user with CNAuthorizationStatus?
You have to use it like this
switch CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)
{
case CNAuthorizationStatus.Denied,CNAuthorizationStatus.Restricted :
//Handle denied and restricted case
break
case CNAuthorizationStatus.NotDetermined :
//Request Access
contactsStore?.requestAccessForEntityType(CNEntityType.Contacts, completionHandler: { (granted, error) -> Void in
//At this point an alert is provided to the user to provide access to contacts.
//This will get invoked if a user responds to the alert
if (!granted ){
//User has allowed the access in the alertview provided
}
else{
//User has decline the access in the alertview provided
}
})
break
case CNAuthorizationStatus.Authorized :
//Do your stuff
NSArray *keysToFetch = #[CNContactGivenNameKey,CNContactFamilyNameKey, CNContactPhoneNumbersKey];
NSString *containerId = [self.CN_contacts defaultContainerIdentifier];
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
self.allContacts = [self.CN_contacts unifiedContactsMatchingPredicate:predicate keysToFetch:keysToFetch error:nil];
break
}
I have created a XMPP Swift Messenger with the eJabbered, but it doesn't save the history.
I searched a lot and could found just answers written in ObjC, in Stack.
For instance:
- (void)loadChatHistoryWithUserName:(NSString *)userName {
NSString *userJid = [NSString stringWithFormat:#"%##%#",userName,self.hostName];
NSManagedObjectContext *moc = [_xmppMsgStorage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entityDescription];
NSError *error;
NSString *predicateFrmt = #"bareJidStr == %#";
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, userJid];
request.predicate = predicate;
NSArray *messages = [moc executeFetchRequest:request error:&error];
}
But I use XMPP Swift Framework with the XMPP ObjC Framework inside. Look at this Git: GitHub
How can I use those snippet in Swift for getting chat history?
If your'e not saving the history locally (i.e. a cache of some sort), then you should probably look into a server plugin that logs the chats and allows you to retrieve them upon connection and login (and entering the relevant room, etc.), if my memory serves me correctly, ejabbered doesn't have that built in (or maybe the payed version does), from my experience Prosody IM server has that plugin and it's pretty easy to setup.
After that, make sure your client side retrieves the history (using a listener, etc.)
Hope this helps.
I am able to access Workout data using workout session but unable to do the same with others such as accessing Height,Weight,Dietary Water, Body Temperature,Blood Pressure etc.
Also i am able to access heart rate but unable to access body temp. Both of them are same vital sign identifiers.
Is it that watch can access only Workout data as mentioned in WWDC 2015 video?
Sample Code:
-(void)bodyTempForLabel :(WKInterfaceLabel *)bodyTempLabel {
HKSampleType *bodyTemp = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
[self readMostRecentSampleType:bodyTemp withCompletion:^(HKQuantitySample *quantitySample, NSError *error) {
if(error) {
NSLog(#"Error Reading Weight From health Kit");
}
self.bodyTemp = quantitySample;
double bodyTempinDegree = [[self.bodyTemp quantity] doubleValueForUnit:[HKUnit unitFromString:[NSString stringWithFormat:#"%#C", #"\u00B0"]]];
dispatch_async(dispatch_get_main_queue(), ^{
[bodyTempLabel setText:[NSString stringWithFormat:#"%f",bodyTempinDegree]];
});
}];
}
-(void)readMostRecentSampleType : (HKSampleType *)sampleType withCompletion:(void(^)(HKQuantitySample *quantitySample,NSError *error))recentSample {
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
HKQuery *sampleQuery = [[HKSampleQuery alloc] initWithSampleType:sampleType predicate:nil limit:HKObjectQueryNoLimit sortDescriptors:#[sortDescriptor] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
if(!error) {
// No results retuned array empty
HKQuantitySample *mostRecentSample = results.firstObject;
recentSample(mostRecentSample,error);
}
}];
[_healthStore executeQuery:sampleQuery];
}
Any help would be appreciated. Thanks!!!
It seems you'll need to use a real device to debug. I'm unable to get any value from HK when running the simulator but it works fine in the Apple Watch. (Using XCode 7 Beta 5).
The apple watch has access to all health kit types (though only a subset of the data). Has your app asked for permission for all of those types? Each type you want to read or write needs to be explicitly asked for when you setup your health store. For example, to read energy burned, distance, and heart rate you need to include:
let typesToRead = Set([
HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned)!,
HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)!,
HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
])
self.healthStore.requestAuthorizationToShareTypes(typesToShare, readTypes: typesToRead) { success, error in
// ...
}