MNCoder

Its been about 3 weeks, but I’m finally done with a piece of work that will be used (hopefully) in the iCloud capable version of Mindnode.

MNCoder is what I’d call a clever hack using NSKeyedArchiver and NSKeyedUnarchiver to help with portability of certain Apple classes between iOS and the Mac. If you worked on both platforms, you’d know that iOS has its own implementation for colors and fonts. With iOS 4 this has been extended to NSAttributedStrings that take Core Text attributes instead of the nicer AppKit additions to NSAttributedStrings.

While I’d admit this is a somewhat complicated way of going about things, 2KSLOC to be exact, I figured this was the most straightforward and intuitive way to help people understand and possibly contribute additional code in the future.

What MNCoder does is that it uses a neutral platform independent NSCoding compliant object to store the base attributes that is needed to reconstruct an equivalent on either platform. Using #ifs, the object will give you the appropriate object. Adding to the system is NSCoder which helps with the finding and replacement of objects at runtime when doing serialization.

Its pretty much like old school language translation. Translate your source language into a intermediate version and then translate that to the target language. Nothing too fancy and easily understood.

The work is released under a BSD license which Markus has nicely given his approval of so here’s hoping it’ll have more contributors as it goes along.

Nice side effect of this is that I’ve had extensive time with Core Text and I’d say its pretty fun.

A Core Data Primer

Everyone’s first encounter with Core Data would be through books and the occasional glance at the documentation. No one tells you what are the base tips in bullet points that you need to know. Having worked on Core Data for the past 9 months, I thought it’ll be a service to the community to at least commit something to Google’s memory.

  • Everything except NSManagedObjectContext is thread safe.
  • Create NSManagedObjectContext in new threads prior to using them. Pass them the NSPersistentStoreCoordinator of any NSManagedObjects across threads is fine.
  • NSManagedObjectID is your friend. Always use it if you are doing threading.
  • NSManagedObjectID is sometimes temporary. Use obtainPermanentObjectIDs to ensure that they are permanent.
  • Getting a permanent ID might cost disk access so use wisely.
  • Process cross context saving on the thread that the NSManagedObjectContext was created.
  • Instrument’s time profiler is your friend to find where Core Data calls are taking a long time.
  • Additionally, you can also get SQL statements that are generated as debug messages in console by turning on a flag.
  • Use as little relationships as possible when fetching objects. Easier to fetch criteria based on the actual operating object and have the fetch also fetch all relationships.
  • Sometimes it is easier to spin off a thread to fetch results and process them before calling the completion block with results.
  • Have a manager to handle all Core Data fetching of objects instead of being smart and trying to have individual managed object subclasses handle everything.
  • NSFetchedResultsController is sometimes a bitch when sending notifications of changed content. Don’t use UITableView’s reloadSectionsWithAnimation and its siblings when crashy happens.
  • Don’t look into [NSManagedObjectContext registeredObjects] to get objects back. They might already have been deleted but still cached. Stupid stupid me.
  • Always test Core Data performance on device.
  • Always do fetches on entities that you are filtering criteria for then use inverse relationships that are prefetched to get the data you really want (Basically think topsy turvy; less database joins the better because this is an object graph).
Check registeredObjects before excuteFetchRequest:Error:

Not too sure if this is the right way of doing this, or if anyone has even tried, but be sure to check the registeredObjects NSArray of the NSManagedContext prior to fetching stuff. This of course only applies to SQLite backed stores, and this is done to reduce SQLite queries and inevitably disk I/O.

You can effectively query the registeredObjects using almost the same predicate as your subclassed NSManagedObjects in order to ensure that the NSManagedObject you want is the same.

Read More

Event-ed NSURLRequest

Have been very much inspired by the work on nodejs. For those of you who don’t know, nodejs is a basically a system to do Evented I/O using Google’s V8 Javascript engine.

One such application of nodejs is the development of servers both HTTP or socket based that doesn’t require the spinning up of threads to handle connections and/or network events. Callbacks are assigned to events and when those events happen, the callbacks are ran. No threads, easy peasey, low overheads, etc.

Currently there are 2 ways to do NSURLRequests. You can either wrap it around a thread and execute the operation synchronously or implement its delegate methods and have it run within the runloop.

JOURLRequest is an encapsulation of the NSURLRequest and its delegate methods to provide for a way to easily implement run loop based event-ed NSURLRequests.

Read More

Competitive Analysis

Background

Recently an app was posted to the App Store that had exactly similar functionality to my first foray into proper iOS development, Traversity.

Initially, I welcomed the new entrant. That lasted until I actually saw the app for myself. Right off the bat within the App Store, I could clearly seem some form of plagiarism (or flattery, but that would require some credit where its due).

Read More

Install iOS apps without iTunes

There might be times where you beta testers are not near the computer they sync their iOS devices with and you don’t have invites to testflightapp. So one of the ways to get your betas onto their phones without requiring a sync is actually by using the iPhone Configuration Utility.

Steps so you can tell them how to get your beta onto their device,

  1. Launch iPhone Configuration Utility.
  2. Click on “Applications” in the sidebar.
  3. Hit cmd + o.
  4. Navigate and select the IPA file that was sent to them. It should appear in the Applications list.
  5. Connect their iOS device and select it under the “Devices” section of the sidebar
  6. Click on the “Applications” tab
  7. Navigate the list till you see your app and hit the install button at the right side of the row.
  8. Voila.

Not so sure about the updating part but it should be as simple as replacing an existing IPA.

Universal Framework

Universal Framework Project Setup

I’ve always loved backend code to be as cross platform as possible. Writing everything based upon Foundation and CoreFoundation only is one of the ways to do that and I’ve always strived to adhere to that principle as much as possible.

While that is cool, the problem begins when you actually want a universal library to work on both OS X and iOS. There is no such thing as Xcode clearly separates both. Understandably, this is seems to be an engineering and architecture decision. Still it would be cool to have a library that you can drop in either your OS X or iOS project.

There is largely 2 schools of thought.

  1. Create your own .framework directory structure
  2. lipo your own static library

There is inherently more flexibility with option 1, but the complexity of building such a framework is huge. Additionally it doesn’t allow you package everything in an Xcode project that can act as a dependency in your other projects.

Using lipo presents its own problems too as a Fat binary must contain code for unique architecture. In short, you cannot have a fat binary with code for the iPhone Simulator and OS X as both contain the same architecture.

After much experimenting I’ve figured out my own solution for this which I feel gives a much better workflow. The genius of the solution is that independently the project will build and create fat binaries for both iPhone Device + iPhone Simulator as well as iPhone Device + OS X.

Additionally, it can be added to existing projects as a dependency and build the appropriate static library which you can then use to automatically link to your project.

One thing to note though with this approach is that if you have the usage of Categories in your code, you will have to add to the Other Link Flags configuration of the Xcode build settings the “-ObjC” flag. Related Technical Q&A here.

Currently two of my projects use such a method of sharing code.

***Update: If you are using the dependency way of getting things done, just link to the “Device” build target. Every time you want to switch the build target you are working on, just do a Clean all. Xcode will build the architecture of either the simulator or the device depending on selection.

On to the steps.

Read More