Speed up fetch of EKEvents - iphone

in my app I'm displaying a list of EKEvents and I would like to display all events of a month in a UITableView, each section containing the respective days. Well, this works and I get all the data, I need, but the fetch is very slow.
The problem consists in events, which spread across multiple days.
Let's say I'm going on vacation from 10th of November until 17th of November.
My search predicate has a startDate with 1st of November and an endDate with 30th of November.
I do an enumerateEventsMatchingPredicate or eventsMatchingPredicate, whatever, both are slow.
I get an array in return with all events taking place in November, as well as my vacation.
But my vacation is just one EKEvent object. So if I want to display a monthly list view of events it would only appear once, on 10th of November, but for reasons of clarity I would to show it on every day it takes place, 10th, 11th, ... 17th.
So what I do is, iterate over each day in a month and do a fetch :-/ This way I get the correct amount of events that take place on a specific day, but ... it feels so complicated.
I already put the fetch into a dispatch_async, so the fetch doesn't block the UI and after the fetch is finished the tableView gets reloaded and cells redrawn. But it still takes time. No userfriendly time.
How do you perform those searches? Do you have any tips on how to speed up the search, maybe a little code snippet or can point me in the right direction!?
Is my question clear? :-/
Thanks,
-Martin.

Fetches are slow especially if there is a lot of recurring events. What I did in my app, is to fetch only once, and parse whole-day-multiple-spanning-day-events to chunks. I abstracted events: I create "date" class, which has NSString properties usable as section titles in table view, and one of its ivars is array with matching "events". "events" are not EKEvents, but my class, to which I copy needed properties from EKEvents. From multiple day spanning single whole day EKEvent I create corresponding "events". Parsing is quite quick - the slowdown is when getting properties from fetched recurring EKEvents.

Related

Google Form and Sheets

I have created a Google Form that is being used daily by multiple people. The data that is being collected goes into google sheets automatically. Is there a way to set up a formula so that the data that is received daily automatedly hides the rows once the day is over? For example I have 10 rows of data that came in on 10/29. Tomorrow 10/30 there will be another 10 entries of different information. I would like the 10/29 data to hide those rows automatically and keep 10/30 date until the next day.. I hope that makes sense.
Thanks

Is this the best way to set CoreData entity variables to 0 every day at 24:00?

I currently have a coreData entity called CalorieProgress, which I would like to reset all variables (calorieProgress, fatProgress) to 0, every day.
I am still quite new to SwiftUI, and the only method I thought of as of now, is to add a Date Created variable to this entity called created, and when the user opens the app, to check if that date was yesterday. If so set all values to 0 etc.
Is there a more efficient way to do this?
Thanks
Your design is good and simple, and a reasonable choice if you're getting started.
It can have trouble, however, when people move between time zones. It is even possible for people to move to previous days this way (most dramatically when they cross the date line). There is no single answer to that question. Your app has to decide what it means by "today" when strange clock events happen. (Users also sometimes change their clock, and you want to behave "reasonably" in those cases, even if it means the data is wrong.)
Having built several of these, my suggestion is to just store raw, immutable, data records, and work out things like resetting values when you're running queries. For example, to work out how many calories someone has burned "today" doesn't require that you set any value to zero. You can just perform a query for records that occur after some time and sum their calories (you can even do this with aggregate queries directly on Core Data).
Core Data can be very fast, but if these queries become too slow, you can store daily aggregation records in Core Data. But keeping the original raw data means that those are really just caches and you can throw them away and recompute any time you need to.
Assuming that a new day starts as midnight (I've worked on apps where days started "when the user wakes up in the morning" which is much more complicated...) you should also be aware of significantTimeChangeNotification which is posted at midnight (and a few other times). You can't use this to launch your app or do processing in the background, but it's very nice for updating your UI if the user has the app open.

Get timeline entry and template used for active complication?

I'd like to conditionally reload my active complication in the requestedUpdateDidBegin function or actually tell ClockKit to set the next check 15 minutes before the end of the current timeline entry, but how can I do that without knowing what's in the current complication?
Here's what I'm trying to do:
if let complications = CLKComplicationServer.sharedInstance().activeComplications {
for item in complications {
// Get timeline entry and template used?
}
}
For the current complication, I can only get the family, but no other info like timeline date or template used. Is there a way to get this?
The complication server requests data from your complication controller, but it's not designed to provide its timeline data to you. All you can find out from the server are the earliest and latest time travel dates.
You'd have to get timeline details from the original data you used to create the timeline entries in the first place.
As for scheduling your update 15 minutes before the end of the last entry, you can very easily schedule that as part of the previous reload request. The very last thing the complication server requests (after reloading or extending the timeline) is the next update date.
Since the complication server has just asked you for the future timeline entries in getTimelineEntriesForComplication:afterDate:, you can make note of the last timeline entry's date, offset it by 15 minutes, then return that new date once getNextRequestedUpdateDateWithHandler momentarily gets called.

Regenerating CouchDB views

Contrived example:
{
productName: 'Lost Series 67 DVD',
availableFrom: '19/May/2011',
availableTo: '19/Sep/2011'
}
View storeFront/currentlyAvailableProducts basically checks if current datetime is within availableFrom - availableTo and emits the doc.
I would like to force a view to regenerate at 1am every night, i.e. process/map all docs.
At first I had a simple python script scheduled via crontab that touched each document hence causing a new revision and the view to update,however since couchdb is append only this wasnt very efficient - i.e. loads of unnecessary IO and disk space usage followed by compaction, very resource wasteful on all fronts.
Second solution was to push the view definition again via couchapp push however this meant the view was unavailable (or partially unavailable) for several minutes which was also unacceptable.
Is there any other solutions?
Will's answer is great; but just to get the consensus viewpoint represented here:
Keep one view, and query it differently every day
Determine your time-slice size, for example one day.
Next, for each document, you emit once for every time slice (day) that it is available. So if a document is available from 19 May to 21 May (inclusive), your emit keys would be:
"2011-05-19"
"2011-05-20"
"2011-05-21"
Once that is computed for every document, to find docs available on a certain day, just query the view with (e.g. today) ?key="2011-05-18".
You never have to update or re-run your views.
If you must never change your query URL for some reason, you might be able to use a _show function to 302 (temporary) redirect to today's correct query.
So your view is not being updated automatically I take it?
New and changed documents are not being added on the fly?
Oh I see, you're cheating. You're using "out of document" information (i.e. the current date) during view creation.
There's no view renaming, but if you were desperate you could use url rewriting.
Simply create a design document "each day": /db/_design/today05172011
Then use some url rewriting to change: GET /db/_design/today/_view/yourview
to: GET /db/_design/today051711/_view/yourview
Create the view at 11pm server time (tweak it so that "now" is "tomorrow", or whatever).
Then add some more clean up code to later delete the older views.
This way your view builds each night as you like.
Obviously you'll need to front Couch with some other web server/proxy to pull this off.
It's elegant, and inelegant, at the same time.

UITableView: Dynamically determining number of sections

I have a medical app for the iPhone that I'm working on, where a user creates timestamped entries for a series of tests performed, which are stored in sqlite for retrieval and subsequent drilldown. In my model class, I have a property uses an NSArray that is populated with these entries, which gets updated as new additions are made in the app.
One thing I'd like to do is display UI behavior similiar to what the Calendar list view does - for any given day, display a section header, that show the name of the day and the date, ans display the entries made for that day.
From a brute force standpoint, I can see how you could precalculate this - as build your list of entries, you could store the entire list in a dictionary, keyed by date.
This seems pretty inelegant though, so I'm wondering if there are other more efficient ways to accomplish this task.
If Core Data WERE available on the iPhone, you could store your information that way instead of sqlite.
Then, when you wanted data for particular day you could search using NSPredicate with a sort descriptor.
Core Data will then return the relevant data sorted according to your descriptor. Nice and neat.
Maybe visit the Apple Dev Center/Forums for some more info on upcoming software...