Core Data

If you’re an iOS developer you probably use Core data every day. I have been learning Core data for the last year professionally, and in my spare time for use in my own apps. I thought I would post some tips that maybe helpful in getting your head around this useful but difficult Apple framework.

Entities and Context

The NSManagedObjectContext is one of the most important classes to understand. Apple calls this the scratch pad another way to think of it is the reference to the your entities world

The general definition of a World is:

  • a group of living things.
  • a period of history.
  • all of the people, societies, and institutions on the earth.

When first learning Core Data the context can be annoying, why cant I can just make changes to objects? But if you think if it in terms of the world in which things happen, it makes more sense.

Every data change event that happens must be tied to a context, and context’s can never be traversed (although they can be merged). The NSManagedObjectContext is your world according to core data and you should structure your code to always have access to it and make changes in reference to it.

Continuing on with the analogy, a living thing is your NSManagedObject. In the context of its world, changes can happen to the living objects, they can be created and deleted. The world itself can even be deleted, which is handy for discarding edits.

Threading is difficult

And so extra caution should be taken. Introducing threading and callbacks can dramatically change the structure of your application without a safetey net (ergo debugging often becomes more difficult).

Core data provides the method - (void)performBlock:(void (^)())block on NSManagedObjectContext as a compact wrapper around operations that can be performed on any thread. But the simplicity of this method is deceiving.

Threaded notifications

If you watch NSNotifications from NSManagedObjectContext for changes in data, you now have to be aware of the thread they are received on. Code that makes changes to your UI such as UIKit must be on the main thread. If you make changes in core data background threads these notifications can appear from background threads randomly and cause crashes that are almost impossible to trace back.

I have shipped code which actually made this mistake, so have built in protection against it

Use child/parent NSManagedObjectContext to make your changes and submit them back to a parent which you know is tied to the main thread. More on this NSPrivateQueueConcurrencyType

Thread contention & atomic operations

You should confine all core data performBlock’s to the one serial NSOperationQueue for safety.

When a performBlock makes changes to data, there’s no guaratee another performBlock is not performing changes on a different thread at approximately the same time. When this happens you run the risk of core data returning errors that make no sense. Enqueueing core data operations into a serial NSOperationQueue will guard against this. I’ve added a short gist to show an example

Migrations

Objc.io has a nice writeup on the subject. After skimming through it you may come to this conclusion which I strongly recommend: Avoid non light-weight migrations.

This is totally possible if you are a bit creative, and its worth the extra effort. These are my reccommendations:

If a properties data type changes, create a new property instead of modifying the existing one

Changing the datatype will not allow light-weight migrations to happen. This is because CoreData doesn’t know how to modify the existing data to conform to the new datatype. If you create a new property and delete the old one, If you care about keeping the old data you have no choice but to venture into manual migration territory.

Use 2 managed object models

If you have data that you need to keep persistent accross app deployments then it maybe worth keep that in a different datamodel (or outside Core Data). One where migrations are important. Data that is purely an offline cache can be kept separate where migrations are not even considered, the data is killed each new app update.

Use magical record for the right reasons

Magical record is an abstraction layer ontop of Core Data. I use it for my own apps, but still know how to drop down to the level of pure Core Data. There’s many resources for learning more, Apple has an write up of its own which maybe a good place to start

Core Data is worth the headaches

I think its a given that every iOS dev wrestles with Core Data during the course of their career, but as a persistence layer it does a pretty great job of managing many of needs of modern iOS apps.

Pretty good

Girl Develop-it

This week I helped with and iOS programming class for Girl developit meetup, hosted by Joe Burgess. The format was little to no pre-requisite programming skill, so the students were writing their first for loops and if statements.

Objective-C is a difficult first programming language, so one thing Joe said in the class stuck with me, that was:

it’s not that anyone is smarter than you are, it’s just they’ve been doing it longer.

He said this a couple of times throughout the lesson and the exercises. I think its a great thing to ground yourself. When something seems un-attainable to grasp in your understanding, it just takes additional time.

Many problems in code come down to your mental model not fitting to whats happening. So you need to debug the code, and adjust your understanding. For that breif period you feel stupid, but it also can be a fun challenge. That is coding.

Xcode Shortcuts

Ctrl + Cmd + J Jump to definition (under the cursor)

Ctrl + 1 Show related items, from here you can select super classes or recent files

shortcut 2

Ctrl + 6 Show document items (methods outlines). Start typing to filter

shortcut 2

Ctrl + a Move cursor to start of line Ctrl + e Move cursor to end of line

Some more well known:

Cmd + Shift + j Highlight current file in group folder view

Cmd + Shift + o Open quickly

Ctrl + Cmd + Navigate back a file

Ctrl + Cmd + Navigate forward a file

Unit Testing Block Based Callbacks

I recently tackled unit testing my AFNetworking client classes, which use block based callbacks, stubbing out block callbacks took some trial and error so is worth of a blogpost.

Take the example method:

1
2
- (AFHTTPRequestOperation*)meWithSuccess:(void (^)(AFHTTPRequestOperation *operation, NSDictionary *responseObject))success
                                 failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure

How would you go about mocking/stubbing this method call? One way is to use OCMock expectations. In your unit test setUp:

1
2
3
4
5
6
7
8
9
10
11
12
13
self.stubMessagesPayload = @{
     @"has_mail" : @0,
     @"has_mod_mail" : @0,
};

_client = [OCMockObject mockForClass:[AFRedditAPIClient class]];

[[[_client expect] andDo:^(NSInvocation *invocation) {
    void (^__unsafe_unretained successStub)(AFHTTPRequestOperation *, NSDictionary *);
    [invocation getArgument:(&successStub) atIndex:2];
    
    successStub(nil,self.stubMessagesPayload);
}] meWithSuccess:[OCMArg any] failure:[OCMArg any]];    

In the actual test, you can change the value of stubMessagesPayload and assert different behaviour. You’ll also notice the block argument is located at index 2, from the documentation:

Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; these values can be retrieved directly with the target and selector methods. Use indices 2 and greater for the arguments normally passed in a message.

The other issue you may face is how to get your class to actually use the mocked version of your object. The code under test may look like this:

1
2
3
4
5
[[AFRedditAPIClient sharedClient] meWithSuccess:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
NSLog(@"success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"failure");
}];

The only way to stub a class method is via swizzling, which can get messy. The alternative is dependency injection, whereby you expose object dependencies using properties or constructor varaibles. Then they can be swapped more easily at runtime, so if the AFRedditAPIClient object where a public property, and RCMessageClient were the class i wanted to test, expose the dependency using a property and in the test asign it to the mock object:

1
2
3
4
5
6
_apiClient = [OCMockObject mockForClass:[AFRedditAPIClient class]];
_messageClient = [[RCMessageClient alloc] init];
_messageClient.apiClient = _apiClient
...
Additional stubs explained above
...

And the implementation changes to refer to that property instead of the class method:

1
2
3
4
5
[_apiClient meWithSuccess:^(AFHTTPRequestOperation *operation, NSDictionary *responseObject) {
NSLog(@"success");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"failure");
}];

E3 Visa Expedition

This post is about a recent US tour I took with the goal of finding work as an iOS Developer in New York. In March of this year I made the decision to quit my job and take the plunge. I was solo, and planned accommodation only 1-2 weeks in advance, so had a huge amount of flexibility.

Another factor for the timing was the WWDC conference. I didn’t get a ticket the amount of side events and altWWDC made it more than worth it.

I was there for 4 months, did a lot of of sight seeing also, but we’ll skip over that.

Getting around

I was ‘on the cheap’ so flew Jetstar Melbourne > Honolulu ($700) then Honolulu > Vancouver ($220). Once on the mainland the Megabus and Greyhound were the preferred mode of transport. Both cheap and allow for great flexibility, the clientele can be pretty rough though.

Looking online

I stayed away from traditional job seek sites, the amount of recruiter spam seemed massive (cybercoders??). Resources:

Events / Meetups

Every city hosts tech meetups and networking events, some resources for meetups:

Interviews

I had about 20 interviews before landing a position, split 50/50 between phone and face to face. Numerous companies follow the Google approach of

  • 1 or 2 phone screens
  • 3-5 interviews in one day, each interview with one person.

Each interview was one or two coding questions and some general resume interogation. Having a portfolio of public facing apps is expected, if not then some open source projects.

Code questions

I found the following process to be helpful for programming questions, taken from: Programming problems : A Primer for the technical interview by B. Green. A summary:

1. Reframe: say the problem back to the interviewer, allowing ambiguities to be addressed. And a way to get hints

2. Write test cases: Builds upon step 1, confirms you and your interviewer are on the same page, will help you formulate your solution. Truth tables, expected output for input, corner cases. write them all down without writing the solution

3. Diagram a solution:(e.g): There’s not many general purpose helpers here, hopefully you will have an idea of how to approach the problem based on the test cases and your discussions with the interviewer. Think out loud, they will provide hints if you are stuck.

4. Coding : I like to start start high level and invent lower level functions, keep variable/function names short as possible.

5. Run the test cases from #2: Confirms your solution and allows interviewer to critque

See also:Interviewing the InterviewerCandidate Coaching Session

E3 Visa

Documents

The formulation of documents for my visa was handled by visanow. The process took abou 3 weeks but was pretty straight forward, they have a checklist style interface and good customer service.

visa list

Interview

Held at St. kilda road Melbourne, I had booked for 9:30, arrived at 9 and waited until 10:30 to be seen. There’s an airport style security check where you’ll relinquish any devices.

I bought everything listed from visanow along with some bank statements, bring everything you think will help, but don’t forget:

  • Printed copy of interview confirmation page
  • DS 160 confirmation page
  • Letter of endorsement from your employer
  • Labour condition agreement (ETA form 9035 & 9035E)
  • DHS Form G28

Done!

Almost hard to belive once it happens, the pipe dream is a reality. My role as iOS Developer at Meetup starts in a few weeks, one adventure ends and another is beginning. Thanks for reading.

Fast HTML Rendering Without UIWebView

This project was created for amrc as a means of rendering HTML rich text content.

The library is built on xml parser hpple. htmpple uses NSDictionary merging to produce an NSAttributedString that represents the given html. Only a subset of html tags are supported, they include those available to any rich text editor, layout such as table is too complex to render with just NSAttributedString.

Rendering non-hyperlink content is a peice of cake in iOS 6 due to the support added to [UILabel attributedString] . If the HTML contains links there’s a bit of additional hacking required. I’ve included a subclass of UITextView to assist with this, although you may want to consider delving into CoreText aswell.

The helper method htmlDataContainsLinks is used to detect hyperlinks and mitigate the performance hit when using UITextView

Check out the project on github.com/amleszk/htmpple