Is it possible to reorder EKReminders in EKCalendar of type reminders?
In native Reminders app it is possible, but I can't seem to find this option in the API.
So, EKCalendarItem objects have calendarItemExternalIdentifier which is unique to the event across devices. You can use this to your advantage for this ordering strategy.
Every time you fetch events from the calendar API, keep track of their calendarItemExternalIdentifier in whatever persistence store you choose (Core Data, SQLite, Property Lists, etc...) and also keep track of it's order.
So if you used Core Data you might have an entity with two attributes, calendarItemExternalIdentifier and order. Now whenever you present the events to the user, query the persistent store for order of each event and display accordingly. If new events come in, find the highest order and increment from there. When the user re-orders, set the order key for the appropriate record in your persistent store.
Related
I have an app that stores lists of strings.
I currently have a CoreData entity for a list and for a user; a user has a relationship to many lists. A user can create more lists.
But I would like to include some default lists. Where should I store these default lists?
The options that come to mind are:
Prepopulate CoreData with some lists
Store default lists in UserDefaults
Store default lists in plist file
Explicitly create default lists in code where they are needed
What is the best way to store a default array of strings for an iOS app?
IMO there is no one-answer to your question an these really depends on your use case.
In general, if your user shall have any interaction with the default lists (manipulating, hide, delete) i would put them in your CoreData.
I assume since you have an entity for the user, you allow multiple different users to use the app on the same device? So if you would store them in the userDefaults you would also have to keep track off the modifications for each user. In general the userDefaults should only be used for "small" data, cf. doc
The defaults system allows an app to customize its behavior to match a
user’s preferences. For example, you can allow users to specify their
preferred units of measurement or media playback speed.
I have an array of event data entries loaded from server. And I think it can be handy if I can use EventKit lib to handle stuff such as event recurrence. But I don't want to make my events to be global events(it probably means saving to the calendar database), which will be showing on all calendar apps. Instead I just want my events to be accessed only inside my app.
Is this achievable?
Thanks in advance!
I would implement the NSCoder protocol on EKEvent, which will then allow you to store your array when the app is terminated and restore it when it loads. There are already various github projects that will do this for you (e.g. https://github.com/yep/DeviceSync-for-iOS/blob/master/DeviceSync/Categories/EKEvent%2BNSCoder.h).
The alternative is to use core data, but you'd have to take care of mapping all of EKEvent's properties into database entities and attributes yourself.
Let's say I have to write an application that must sync with one of the calendars available on the device. Let's assume that I have "Action" objects that have a start date, end date, recurrence etc.
Device A: I create "Action" objects and then sync them using EventKit with my iCloud calendar named "Foo". I get some unique identifiers that I have to link them with my "Action" objects in order to know which one to update/delete in the future. Then I sync my "Action" objects with my own server.
Device B: I get the "Action" objects from the server. I modify them. I have to update the calendar items. What happens if I don't have the "Foo" calendar set on Device B? What happens if I do have it?
I guess I need to use the calendarItemExternalIdentifier and not the calendarItemIdentifier property in order to identify events uniquely across devices that use the same calendar, right?
Is that calendarItemExternalIdentifier given in the moment of creation of the calendarItem? or is it given by the iCloud server? Do I need internet connection for this to work?
The documentation for the calendarIdentifier property states:
A full sync with the calendar will lose this identifier. You should
have a plan for dealing with a calendar whose identifier is no longer
fetch-able by caching its other properties.
What does a full sync even mean?
calendarItemExternalIdentifier is available as soon as you save (with commit) a calendar item. But, there are situations when the calendarItemExternalIdentifier is later changed, when the calendar item is synced further to the server (e.g. if it's an event from an Exchange account).
All the other identifiers are not shared between devices (this includes identifiers for sources and calendars), so the best option is sticking with calendarItemExternalIdentifier.
A full sync with a calendar can occur when the user sets up a new source (e.g. the user removes and adds the same Exchange account). There may also be different situations that cause a full calendar sync.
calendarIdentifier is a local identifier, so it won't be of much use in your case (except if you want to create a workaround for the issue with calendarItemExternalIdentifier changing).
As mentioned earlier, the calendar and source identifiers are not global, so it would be near impossible to know if "Foo" calendar is setup on a different device, or if the "Foo" calendar is the same "Foo" calendar from your other device.
Usually, if you find your Action object on the new device, you can assume that the calendar that it belongs to is the same as the calendar from the different device.
One way to go about it, when updating your Action objects, would be to save the changes (as usual) to the server. Each of the devices (including the one that made the change) would then search for the corresponding calendar item, and update it if it's found.
I'm currently doing something similar, and this is probably what I'll end up doing.
A better alternative (probably more time consuming as well) would be to have the server connect and sync with the external sources (CalDav, Exchange etc.).
I use the kABpersonModificationDateProperty to detect AddressBook records that have been added/modified since the last startup.
Is it possible to detect which records have been deleted since my last startup?
I dearly wish it were so.
Your only option here is to cache all the record IDs, and then compare the full list at startup.
You're still exposed to situations where iOS rewrites all the IDs (such as when syncing via iCloud), in which case it will appear that all the records were deleted and an entirely new batch added. You can try to recognize cases where the ID was changed on an existing record by comparing fields (such as first/last name).
I have some data that needs to be loaded from the server (backend). For example, let's just say I have an entities of user and event. The relationship between them is many-to-many (user can attend many events and event can have many attendees). All the data is stored remotely on backend and locally in Core Data. When I download data from backend I convert it into NSManagedObjects and store it in NSManagedObjectContext. Everything's very simple, but...
When I download a list of events I want to know, how many attendees this event has. But I cannot download a list of users in the same request, because it's totally overkill. What I need is to download, let's say, a list of users' unique ids so that I can have two things: total number of attendees and means to download detailed data of concrete users (via unique id). Or there's another example: I need to know total number of attendees and download a limited set of them, so I can create some entities in CoreData, but not all of them.
So the main question is how am I supposed to store such information in my CoreData? Meaning I need to know that for some entity there are some related entities in relationship that are not actually currently present in CoreData, but I know how many of them there should be. The first thing that came in my mind is to have a attribute called something like usersCount in my event entity, but that seems to be kind of dirty. What is the best practice for such situation?
Please comment if the question is not clear enough so I can maybe add some more specifics.
When you download an event with a list of corresponding user ids, then you can create
the Event object and also the related User objects, but you fill only the "userId"
attribute in the user object.
Later, when you download the complete user info, you update the existing (incomplete) objects
or create new user objects. Implementing Find-or-Create Efficiently in the "Core Data Programming Guide"
describes a pattern that might be useful.
So the idea is to create Core Data objects with incomplete information first and update the
objects with detailed information later. The advantage is that you can set up all relationships immediatly, and e.g. counting related users works even if the user information
is yet incomplete.
There is nothing dirty about having an attribute to store the count, especially if those entities are retrieved and paged via separate requests.