CloudKit: can't discover identities - ios

Pretty new to CloudKit. Trying to get all the contacts who are using my app. According to the docs and the tutorials out there I'm calling this:
discoverAllIdentities(completionHandler:)
The issue is that only my user (the one who is logged in on the device where the app is running) is returned. So I did some digging and noticed that if I call this one:
discoverUserIdentity(withPhoneNumber:completionHandler:)
and I use phone number directly the user is returned.
So after more investigation, I figured that the reason I do not get those users is that in my Contacts those users do not have their iCloud email stored. So once I add the email, they are returned by discoverAllIdentities(completionHandler:). So it appears the default implementation of that method is tied to iCloud emails for the discovery instead of phone number.
Is it possible to use phone number for discoverAllIdentities(completionHandler:)? Since, I don't think that as you add a new contact you would record anything but just phone number, so you will be missing to discover all those users.
Any kind of help is highly appreciated.

Related

CloudKit share participant no longer returns name

I'm working on an app that uses CloudKit sharing functionality. The sharing features have been working great, but recently I no longer get the user names back from the CKShare.Participant when a user accepts the sharing request.
Details
I'm using the built-in UICloudSharingController to set up the share, which works and sets up the share properly.
When the invited user accepts the share, the owner gets a notification of the change in the zone and then fetches the CKShare.
The fetched CKShare object has an array of share participants (CKShare.Participant), which has a nameComponents property. I've used this in order to get the first and last name of the participants to display in the UI. This was all working fine until recently.
Now, however, I'm only getting values in nameComponents for the owner of the share. The accepted participants have nil values for the nameComponents.givenName and nameComponents.familyName.
I have not changed anything in this part of my code in some time, so don't think I've caused this. I've tried this on iOS 11, 11.4, 12, 12.1 and all have the issue. This leads me to believe there might have been a change on the server side from Apple.
Note
I am not requesting .userDiscoverability permissions. I have not had to do that in order to get the names once a user accepts. I realize that I can request that and then use CKDiscoverUserIdentitiesOperation to get the names. But I'd rather not as I don't want the dialog, which is confusing for users.
Has anyone seen this change? Or better, yet, does anyone have any suggestions for tracking down the cause or fixing it?
Thanks.

Can CloudKit user phone numbers be retrieved using `CKDiscoverAllUserIdentitiesOperation`?

Background
I am retrieving all the users for my app using the recommended CloudKit operation, CKDiscoverAllUserIdentitiesOperation.
This operation is designed to returns each user's info in a CKUserIdentity object. The lookupInfo attribute of the user identity has fields that can contain the user's email address and the user's phone number.
e.g.
user.lookupInfo.phoneNumber
user.lookupInfo.emailAddress
Question
When I run this operation, I only ever get each user's email address. The phoneNumber field is never populated.
How do I retrieve these user identities and have them include the user's phone number? (Is this possible?)
Additional Info
I am able to retrieve individual users with their phone numbers using the discoverUserIdentity(withPhoneNumber... CloudKit function, so I know that these accounts are linked to phone numbers.
All you get is the email. That's it. It's not possible to get any more info than that using CKDiscoverAllUserIdentitiesOperation. And that is only for users that have agreed to be looked up via email while using your app.
The only time the phone number is filled in is if you specifically lookup the user by phone number. Of course that's kind of pointless since you already know the phone number.

How whatsapp get updated contacts from addressbook faster in iOS?

My findings
I am designing a logic to sync contact with my Backend. I gone through some apps that doing same thing in IOS. I will take the example of WhatsApp, I found that When I update any contact in Native Addressbook, it reflect that change into Whatsapp withing a fraction.
My Concern
I just want to know that how it is syncing in a very faster way. Even a new contact gets synced with its Remote server and get displayed on contact, and with the ability to initiate Whatsapp chat if that number is registered one.
Summary of Queries
So, in nutshell my queries are,
How Whatsapp is syncing the contact?
How whatsapp is getting just updated contact list from Native Addressbook (if it's doing so) ?
How whatsapp is just getting just new Contact added in addressbook, is there anything that manages like timestamp or anything else?
I know the following things are there like,
ABAddressBookGetPersonCount
ABAddressBookGetPersonWithRecordID
ABAddressBookCopyArrayOfAllPeople
Using the ABAddressBookGetPersonCount i can know if any new contacts are there but still how i will be able to know its Record ID without iterating each contact using ABAddressBookCopyArrayOfAllPeople
So i am just asking for the way to get just updated list.
The way to do this is by registering an external change callback. This way, your app will be notified of any changes to the address book as soon as they happen.

Getting contacts who own an iDevice

Is there a way through addressbookUi framework to get only the contacts who own an iDevice? The check for example is done in the messages app for iMessage. But is this available for developers? Or is there another way to check for this? Thank you in advance..
You could check, for each address book record, if there is a phone number of type "iPhone" (represented by the constant kABPersonPhoneIPhoneLabel). There's really no way of knowing for sure which of the contacts "owns an iDevice" anyway, but if there is an iPhone number for them in the address book record, then there's a good chance of them using an iPhone. Of course, it's another story altogether how that information got in your address book, and whether it is reliable.
No there isn't... The SMS app would be checking with apples servers to see if the phone number is registered with iMessage or not.
This is not a publicly accessible API.
I guess you could hash then send the users number to your own remote database and then compare contact numbers in another users address book against your database to see if they are users of your app... It's not really what you asked to do but it's the closest solution I could think up

Inviting users to an IOS app

After registration, our app prompts users to invite her friends (aka phone contacts) to use the app too. This allows us to send an email/sms to the useer's contacts with some sort of invitation key. Works fine for a web version app, just embed the key in the url you provide in the invitation.
I'm having trouble figuring out how to make this work smoothly with IOS only. It would be brilliant if I could send the invitee a link to appstore.apple.com/myapp?registrationKey=abcXYZ and have the key magically available to my app once it's installed, but I guess this is a lot to hope for?
The obvious way around this is to make the user manually enter their registration key on first launch, but this seems less reliable and (to my mind) adds friction to the UX.
Has anybody come up with something clever to get around this?
Here is what is flowing through my brain on how to solve this solution, please note, I have not vetted, psudeo-coded, coded, or applied this theory.
Since you will know who is being sent an invitation, save that data to your database with a relationship to the user sending and a unique id to the user being invited (email address if its in the contact's card). When new users sign up scan the database for invitations, if one is found present it to the user asking We're you referred by <existing user>? Once the new user selects their response continue through the registration process, updating the relationship table accordingly and applying any extra settings you need to for the referral.
This combines automatic referral tracking with referral codes for a basic, straight-forward, almost (but not quite) fool proof method to make sure referrals are linked to the right users.
As far as I can tell, the App Store provides an information firewall between an invitation and the installed app.
The closest workaround I've seen is the following:
email link sends you to your website
the website logs reference information in the URL and the IP address
the website instantly redirects you to the App Store (if iOS detected)
user installs the app
user loads the app
app contacts your website, IP addresses matched ... BINGO
Obviously not a secure method though.
There are many failure cases:
business networks commonly share IPs
home and mobile networks release and reuse IPs
The more is frequently used to resolve cases where its good enough to know that the user 'almost-certainly' was referred to download app by the email.
For example, it can be a good mechanism to prompt the user with a "who do you know" question in an app and limit the options based on the (IP+reference) data. If they pick the original poster, then maybe that's good enough, and then you can attach any other data that the inviter provided.
(Full disclosure, currently work at Branch)
The best solution to this is to fingerprint a user. This requires you to do the following steps:
For each user, using your own domain, generate a link for said user. So, right when they complete registration, generate their unique URL, that contains the invitation key.
For anyone clicking this link, they will redirect to Safari first. When they do, capture their IP address and iOS operating system version from the headers and user-agent.
Save this data on your server, and set window.location to your iTunes url.
If the user downloads and consequently opens, inside AppDelegate.m, send a message to your server with the IP address + major/minor/min version you collect upon app launch. If it matches with what you have on the server, you can now pass that invitation key back to the new user.
It's not perfect, and has the ability to misattribute. You could also use branch.io, where all of this is taken care of (link-generation, fingerprinting a user, attribution). Branch also drops a first party cookie and ties it with the device level ID, so attributions are much more accurate.

Resources