Ad

Our DNA is written in Swift
Jump

Reverse-Engineering the Apple CalendarView

Now that I am able to work on my apps full time I finally get to fulfilling my user’s wishes. Amongst those, for iWoman, was a Calendar view. I did not want to use another person’s code and deconstructing something that Apple made proved to be extremely instructive.

Here a video demonstration of my result so far. Please disregard the incorrect labelling at the top. At least this proves that this is not fake. 🙂

The whole thing consists of three classes, a CalendarViewController which takes care of the general management of views, a CalendarDayView which derives it’s capabilities of responding to target/actions from UIButton and a CalendarHeadView which is everything you see at the top.

What makes it look special and professional is that you have multiple gradients at work. Besides of the obvious one at the bottom, there are black and gray gradients shading most of the labels. The regular gray background I custom draw in drawRect, but the blue selected box was too complicated so I opted to use a UIImage for that.

For most of the calendar calculations I needed an NSCalendar, so I made a helper class with category extensions to NSCalendar to give me things like first day of next month, first day of current month, number of days and so on. I found that I could quite reduce my memory footprint by reusing things. Like instantiating the NSCalendar just once for the whole view controller.

By far the trickiest business was to properly set up the grid of CalendarDayViews on an invisible view where I enabled cropping of children so that stuff could appear smoothly from below the gradient at the bottom. The animation itself is trivial, but it took some time to figure out that I would have to overlay the bottom or top line with alpha 0 with another set of days when going forward or backward and then animate it to 1 so that the selected day would move from being a gray rectangle (if you tap on a day that belongs to another month) to being blue.

For quickly switching between months you can tap and hold one of the arrows. For this I did not need any animations, so I pimped the method to set up my sheet with an animated: BOOL parameter. For regular switching this would be YES, for fast-switching it would be NO. Et voila!

That all worked nicely until I started to use it on device. I was asked about the performance on device, especially for fast-scrolling. I found that I could tremendously improve this by reusing the UIViews I am creating one for each day. Before my optimization all subviews to my sheet where removed from superview when they left the visible area. Since the sheet was the only view retaining them this also lead to their deallocation. Then I simply introduced an NSMutableSet to hold onto removed Views and also reuse CalendarDayViews from there. This speed things up quite a bit. Reuse if you can as much as you can!

Next things to do on the CalendarView control is to add a table view below it, so that I can query a data source for table view sections and rows pertaining to the currently selected date. I plan on using this in version 2 of iWoman, the first major update to my best selling app. I owe this to my customers since I did not get to update this app in over a year.

CalendarView will be the first of many things in my “Dr. Touch Parts Store” where you can obtain high quality components to use in your own projects for a small donation. The concept is that this small amount of money pays for the time I need to continue to improve it, support it and help you with implementing it.


Categories: Projects

5 Comments »

  1. Great work, as usual. Looking forward for that Parts Store to be available.

  2. Awesome! Really looking forward to the Parts store…

    One feature request though: would it be possible to use dragging (optionally) for selecting date ranges?

    Cheers,
    -J

  3. Probably doable. But how would that work? With a property that when set keeps selected days selected while you drag?