Checking if any contact in contact app has been changes (Swift) - ios

Right now I build an app that provide sync contacts. For that, every time the app comeback to foreground, I check all contacts(CNContact) and compare to my contact in app's core data and detect if any contact that different and merge the data. It works okay but it takes a lot of memory.
Is that any way to detect if any contact in contact app has changed without comparing all contact?

Related

What is considered too heavy for UserDefaults?

I'm building a simple iOS app that will be the first I'll have put on Apple's App Store. At one point, the app accesses the user's contact list and lets them select any number of contacts they want to save as favorites.
For ease of building version one, I am currently using UserDefaults to save these favorites. While it has worked well in my limited testing, I know that Core Data and CloudKit are stable options for larger solutions.
For an app like mine, where I'm only using UserDefaults to save a select number of contacts as favorites, is UserDefaults an adequate solution? Or should I transition to something more robust like Core Data or CloudKit? There is no limit on the number of contacts a user could select as a favorite, so there is the edge-case possibility of a user selecting all of their contacts one by one and attempting to save them all as favorites.
If the user gets a new phone and loses all existing data due to UserDefaults being local on the device, it would not take long to get this app back to where they previously had it.
You can use CoreData to store favorite contact locally for large data as per your concern. Now when user switch device or delete app then all data will removed. So for that you can sync with cloudKit or other option is backend server. When user add any contact as favourite same time that contact will add to Core data as well as in backend server. You can sync this backend server data when user login first time in the app, then you no need to sync again. other all thing are as per requirement.

Independent operation of watchOS app when sharing app with iOS app

My iOS app uses CoreData as its data store and I have added a watchOS app to accompany it. Currently the workflow between the iOS and watchOS apps is as follows:
The watchOS app exposes a menu representing a subset of functions available in the iOS app
Choosing one of these options sends a message to the iOS app telling it which option was selected
The iOS app responds by packaging up any data needed by the watch for that particular function into a dictionary and sending this back to the watch in the reply handler
The watchOS app presents an interface to the user allowing them to change the values in the data
Each change sends a message to the iOS app which updates the core data store with the new values
This is working fine but clearly requires the phone to be connected to the watch throughout the use of the app for it to work. I'm wondering whether a model like the following would be possible:
As above
As above
As above
3a. The watch stores the data locally
As above
Each change updates the watch app's local copy of the data
The user can later check the data back in to the iOS app at which point it is merged into the core data database
I can guarantee that conflicts would not be an issue as the user would never be able to modify data which had already been created on the phone (it is not a requirement of the app to be able to do so).
So my question is, would the latter case allow the watchOS app to operate independently of the iOS app with the exception of transferring data, and is this a preferable method to the way I am handing this currently?
It's simpler for your watch app to be dependent on the phone. It's more complex for it to operate independently of the phone. Only you can
answer whether the added complexity to support true independence is worth it, since you're the person who has to implement, support, and maintain any additional code needed.
Do the changes make the watch app independent?
No, they don't let the watch app operate independently, since the watch still must request/receive data from the phone during steps 2 and 3.
For the watch app to be completely independent while away from the phone, it would have to query a local copy of the data which the phone updated as needed, instead of requiring the phone to send any remote data that the watch needs.
Is the change preferable?
Not as it stands. Your proposed change to defer updating the phone (even though it's still reachable) may require much unnecessary code related to locally storing data for the present, and merging updates back to the phone in the future.
Also, while you promise there presently is no merge conflict to deal with, there's no guarantee that any revisions you make to your app in the future won't introduce the possibility for conflicts to occur.
If you choose to establish two persistent stores, it would make your app less fragile to implement a merge policy now, to avoid your updates from completely failing to save, should a future conflict occur.
The real question...
Is the freedom to operate away from the phone (for hours) worth showing stale (or possibly misleading) data to the user?
Unless you also provide an indication showing when the data was refreshed by the phone, the user may assume that the displayed information is current and accurate, even though it may be hours old.
This adds more complexity to the watch app either in the user-facing UI or behind the scenes to handle stale data.
For your consideration, Apple Watch's Weather app simply shows no data at all when it can't obtain the current weather data from the phone (since users would want to know the current temperature and chance of precipitation).

Is it possible to programmatically disable an ABSource or ABGroup in the main Contacts app?

I'm building an alcohol prevention app and one of the features is to block the user's contacts for a given period of time so that they don't irresponsibly make drunken calls/texts to people.
The current (and very old) version implements it by letting the user select in-app which contacts to block. Then, it directly changes the selected contacts' phone numbers to an invalid one. That way, even if the user goes to the Phone or Messages app, the call or text won't be sent to the contact because the number is invalid.
I very strongly dislike this approach because it screws up with your address book which can be synced across multiple devices. What I have in mind is to:
Create a separate ABGroup or ABSource of contacts for my app
Copy all the contacts from other groups and sources into my app's group or source
Falsify all the contacts' phone numbers in my app's group or source
Disable all the other groups or source in the main Contacts app.
My question is: Is this possible? I looked into the ABSource and ABGroup references but can't find properties to disable them, but I'm hoping it's available somewhere in the SDK and that I'm just being blind.
If it's not possible, I'd be happy to hear any ideas for alternative implementations (iCloud backups, write original data into a file and screw up everything then put it back later, etc).

iOS Assets Library: permanent unique key for photos(identify photos between multiple runs)?

Say I have an app which allows user to pick some images from assets library.
When running for the 1st time, user picks some photo, at the 2nd run, when user wants to pick photos, I'd like to set the photos user picked last time as already selected.
How do I identify photos between multiple runs of my app?
iOS apps usually don't get terminated, but get sent to background - state will be unchanged when getting back to foreground
For case your app get's terminated anyway, you can store data in NSUserDefaults, CoreData, the file system or the keychain. In your case it sounds like NSUserDefaults would be a good choice. Don't forget to restore last states on app start.

tracking certain email change in ABRecordRef

I am creating an application to sync the addressbook. I have synced the addressbook records into the local core data based database and I could already fetch them. Syncing a record is easy using the ABRecordId. I store the record id for certain addressbook record into my local database, and so I can fetch a certain record based on the id. I can also implement the callback by implementing the ABAddressBookRegisterExternalChangeCallback. But is there a way to track change of a particular email. A user could change his email, how is it possible to know if a certain email has changed.
There is no way to attach a "listener" that will somehow call a function in your app every time someone edits a contact. But, there is a way to keep your app up-to-date:
Store a variable in NSUserDefaults that contains the date of the last time you imported new contacts from the phone.
When your app resumes from the background or opens for the first time, you should query the phone's contacts for all of the records that have been modified since the date of the last time you synced with the contacts. This way, you can only process the updated contacts without iterating over every saved contact every time.
You should be able to sort the person records by this property:
kABPersonModificationDateProperty (reference)

Resources