My Web Log Book

NSCalendar is always looking out for you

Just got this message from calling -[NSCalendar components:fromDate:toDate:options:]

2014-04-16 19:34:12.319 App[6140:3c0b] *** -[__NSCFCalendar components:fromDate:toDate:options:]: fromDate cannot be nil

I mean really, what do you think that operation is supposed to mean with a nil fromDate?

An exception has been avoided for now.

A few of these errors are going to be reported with this complaint, then further violations will simply silently do whatever random thing results from the nil.

Here is the backtrace where this occurred this time (some frames may be missing due to compiler optimizations):

(
	0   CoreFoundation                      0x33e8548f  + 86
	1   App                                 0x00153825  by me
	2   App                                 0x00155ec9  by me
	3   libdispatch.dylib                   0x3bf7411f  + 10
	4   libdispatch.dylib                   0x3bf7399b  + 146
	5   libdispatch.dylib                   0x3bf73895  + 36
	6   libdispatch.dylib                   0x3bf82215  + 192
	7   libdispatch.dylib                   0x3bf823b9  + 84
	8   libsystem_c.dylib                   0x3bfa8a11  + 360
	9   libsystem_c.dylib                   0x3bfa88a4 start_wqthread + 8)

Objective-C humor

I came across a bug in my application today where the -main method was overridden in a subclass but the superclass implementation was not being called. The solution was straightforward though. Thank you [super main].

Protected stuff for Objective-C subclasses

That’s a good name for protected extensions for a subclass that I came across in UIGestureRecognizerSubclass.h
@interface UIGestureRecognizer (ForSubclassEyesOnly)
…

Date parsing performance on iOS (NSDateFormatter vs sqlite)

Many web services choose to return dates in something other than a unix timestamp (unfortunately).

Recently I set out trying to identify performance bottlenecks with a large import operation in our iOS app. Having tweaked most of the variables, I was surprised to find out that date parsing was actually one of the biggest bottlenecks. The date parsing was done using NSDateFormatter using an ISO-8601 formatted date that looked like this:

2013-09-07T23:45:00Z

That looks simple enough. We had the NSDateFormatter’s format setup with a timezone of +0 GMT, and everything was great, expect parsing dates like this was consuming around 20% of the entire import operation. To provide some context, we were testing the import performance by importing roughly 250,000 objects into a SQLite database, and each object had 4 dates associated with it. That meant that we were dealing with a million dates, and parsing a million dates can get expensive.

Almost all of that time was being spent inside NSDateFormatter’s dateFromString: method, so there was not much we could do to optimize things ourselves.

The main goal was to get a unix timestamp from the ISO date. Luckily for us, SQLite is quite good at parsing some ISO-8601 dates and works blazingly fast. Here’s how SQLite can parse the above date:

sqlite> SELECT strftime("%s", "2013-09-07T23:45:00Z");
1378597500

Let’s convert this to use SQLite’s C library.

sqlite3_stmt *statement = NULL;
sqlite3_prepare_v2(db, "SELECT strftime('%s', ?);", -1, &statement, NULL);

sqlite3_bind_text(statement, 1, [dateString UTF8String], -1, SQLITE_STATIC);
sqlite3_step(statement);
sqlite3_int64 interval = sqlite3_column_int64(statement, 0);
NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval];

Looks ugly, but we’re trying to solve a genuine problem here. So, how did this do in a performance run against NSDateFormatter? About 1400% faster. To parse a million randomly generated dates on an iPhone 5 running iOS 7, NSDateFormatter took a whooping 106.27 seconds, while the SQLite version took just 7.02 seconds.

Here’s a link to a gist containing the source code used for this comparison.

If you’re curious as to what SQLite is doing under the hood, checkout the date related code in SQLite at http://www.sqlite.org/src/doc/trunk/src/date.c. It mentions that the conversion algorithms it is using are from a book named Astronomical Algorithms by Jean Meeus.

95% of the performance problems are our assumptions.

—Found this brilliant quote on a Stackoverflow comment. Unfortunately, I can’t find a link to the source.

iOS 7 and Skeumorphism

I’m glad to see Apple take skeuomorphism to the next level in iOS 7. It always felt like what the design community really hated was not skeuomorphism, but the emulation of existing materials like green felt or leather. Both these concepts would appear to be the identical at first sight, and they absolutely are, until we consider the idea that skeuomorphism extends beyond just visual emulation of materials. If the sound made by the Camera app in an iPhone is skeuomorphic because there is no mechanical shutter in an iPhone, then sound can also be skeuomorphic, and the definition of this term must include design elements beyond just visual looks.

One concept that spans both space and time and is omnipresent in iOS 7 is depth which seems to be heavily baked in to iOS 7. The depth and the parallax is not just on the home-screen but it’s pervasive throughout most elements in the OS.

Let’s visit the alternative definition of skeuomorphism on Wikipedia before we come back to the parallax. Wikipedia defines it as:

"an element of design or structure that serves little or no purpose in the artifact fashioned from the new material but was essential to the object made from the original material"

When we talk about a phone or a tablet, the new material is the digital screen, speakers, camera, etc. Parallax is an element of design or structure that serves little or no purpose on this screen. The original material here is perspective in a three dimensional space. By this reasoning, iOS 7 is heavily skeuomorphic, and Apple didn’t get rid of skeuomorphism in this version, but instead turned it up a notch.

Skeuomorphism is dead. Long live skeuomorphism.

Building Dart on Snow Leopard

I was stuck at the unsupported GCC error in building Dart on my Snow Leopard. The fix was simple - to remove the explicit version requirement, and let it use the system default. Hope it doesn’t break anything.

Unsupported compiler 'GCC 4.2' selected for architecture 'x86_64'

Basically we have to clear out all references to GCC 4.2 from


GCC_VERSION = 4.2;

to


GCC_VERSION = ""

Since this version has been references in a thousand places, a global search and replace was needed. I am inside the dart/ directory.

$ find . -name "*.pbxproj" -print -exec sed -i 's/GCC_VERSION = 4.2/GCC_VERSION = ""/g' {} \;

And ** BUILD SUCCEEDED **

Cool!

Responding with non-empty JSON when updating a resource via PUT in Rails 3

Rails 3 responds with an empty object when making PUT requests to update a resource. This could be undesirable for some cases, and certainly is in our case where expect the JSON representation of the modified object as the response.

The quick-fix is easy - we override the default behavior of respond_with using a block that returns forces the response to be the complete JSON object.

respond_with(@program) do |format|
  format.json {
    if @program.valid?
      render json: @program
    else
      render json: @program.errors, status: :unprocessable_entity
    end
  }
end

A neater fix, at least for me, would be in Rails itself inside the Responder class. GET and POST requests already work as expected. For other requests Rails returns an empty response. This is how things look right now

# This is the common behavior for formats associated with APIs, such as :xml and :json.
def api_behavior(error)
  raise error unless resourceful?

  if get?
    display resource
  elsif post?
    display resource, :status => :created, :location => api_location
  elsif has_empty_resource_definition?
    display empty_resource, :status => :ok
  else
    head :ok
  end
end

Instead of responding with an empty resource for non GET/POST requests, we could have returned the resource itself for PUT requests as well. Here’s how my ideal solution would look like (notice the elsif put? line):

# This is the common behavior for formats associated with APIs, such as :xml and :json.
def api_behavior(error)
  raise error unless resourceful?

  if get?
    display resource
  elsif post?
    display resource, :status => :created, :location => api_location
  elsif put?
    display resource, :status => :ok
  elsif has_empty_resource_definition?
    display empty_resource, :status => :ok
  else
    head :ok
  end
end

Now what can I do to get this merged in Rails?

Linker errors with iOS 5 and libz

So this has happened a few times across different projects where my iOS app failed to compile. The first one was particularly sad because when building a static framework that I include in my work app, because of libz. We were referencing libz.1.2.3 which is apparently not included in iOS 5 SDK. I think it only contains version 1.2.5 now. The worst part was that libtool was failing, and it gave absolutely no clue as to why. The error simply said,

libtool failed with error code 1

Bravo. After head-banging for a couple hours and trying random stuff, I removed libz and suddenly the project compiled.

In another project, XCode for more helpful and guided me to the error rightaway by uttering some useful errors,

ld: library not found for -lz.1.2.3

Lesson learnt. Now I’m just referencing libz.dylib in the project as it is a symbolic link to the actual library and hopefully will always be there when needed.