The Dangling Pointer

Sh*t my brain says and forgets about

Blogging U.’s Photo 101 Course: Post a Photo a Day

WordPress.com’s Daily Post is holding an online photo blogging course called Photo 101.  It starts Monday, November 3rd and it goes through November 28th.  Each day a topic is presented and it’s your challenge to post a photo that is your interpretation of the topic.  Along with the topic are tips and tricks for you to learn.  Posts are tagged so they’re visible on the WordPress.com Reader.  WordPress.com-hosted sites and self-hosted sites are both encouraged to join in!

Visit WordPress.com’s main blog for an intro post regarding this course.

I will be posting the daily photos over at Astral Imagery, my photo blog.

Core Data Object IDs can change

I thought I knew a lot about Core Data with having used it a lot over the past years.  Today, I learned something new that I feel like I should have known for a long time.  NSManagedObjectIDs can change.  Seriously.

Identity in Core Data is really a tuple of (file aka store UUID, entity name, primary key). This can be captured in the -URIRepresentation from NSManagedObjectID. However, that requires using the same file, and not resetting the primary keys (e.g. changing the store UUID, or delete the file and creating a new one, or performing a not-light-weight migration)

If you want a different notion of identity, you can just add an UUID string as an attribute to your entity. A separate mapping table is not recommend. The 2 apps should agree to use the same UUIDs for the same identities.

– Ben

Ref: https://devforums.apple.com/message/480640#480640

Ben is one of the core developers of Core Data at Apple.  The last sentence describing ways primary keys can change blew my mind when mentioning “not-light-weight migration”.  In WordPress for iOS we sometimes have to perform heavyweight migrations – especially in the case of removing objects or combining object ancestries.  In a number of cases we use NSManagedObjectID’s URIRepresentation and throw it in NSUserDefaults for retrieval later.  Turns out, that ID isn’t stable enough between migrations.

The solution, as Ben points out, is to create a UUID and make the ID yourself upon initial persistence.

Mind blown.

Anxious

 

UPS is delivering my iPhone 6 Plus today.
UPS Sign

Code Dependent

Plus using dependency managers like CocoaPods tends to get unwieldily the larger your team gets. Not only do you have to worry about the libraries as dependencies but now you have to worry about the versioning of the dependency manager. Oy!

2014 Automattic Grand Meetup

At Automattic we all are a distributed workforce – we all work from all over the world.  Every few months we meet up with our teammates and work on projects designed to be started and finished within the week.  Once a year the entire company gets together in one place and we affectionally dub it the “Grand Meetup” (abbreviated GM).  This year, we all met up in Park City, Utah USA at the Grand Summit Canyons Resort.

We do a lot of things at the GM.  Primarily the GM is meant to be a restorative time to emotionally connect with our peers.  This comes in the form of group lunches and dinners, flash talks, recreational outings, and just sitting on couches talking over a coffee or beer.  Since we don’t often get to see each other (especially those of us who don’t directly work together) this is a chance to establish the inner voice we have that represents someone’s online persona.  When we see each other online after a GM, we can emote better because everyone has gotten to know our personalities.

We also are required to pick one of three things to do for real work during the GM: work on a project (to be assigned), work on your day to day project if you need face-to-face time, or participate in a learn-up group (teaching or learning).  I ended up choosing to teach a class on iOS development to seven other coworkers.  It was fantastic.  Almost everyone submitted a pull request to WordPress-iOS by the end of the class.

I didn’t take a ton of photos at the meetup but here are some of my favorite:

Mac OS X Server Time Machine Volume Filling Too Fast

I’ve been noticing on my Mac OS X Mavericks 10.8 Server I have running in a data center has been filling up its Time Machine volume way too quickly.  The backups are continually huge and only about a week fits on the second hard drive inside of the Mac mini.  Every time the machine backed up it was taking up so much room that previous backups had to be deleted.

I searched everywhere and couldn’t find an issue.  I looked in console logs for Time Machine and couldn’t find anything definitive as well but it looked like it was something in /Library/Server.  I realized that it must be a file or set of files that are always being written to so they’re always backed up every hour or so.

I had tried some command-line tools like “du” but the usage was so many levels deep it was hard to pinpoint.  Finally I grew a brain and installed DaisyDisk on the server to see what I could find.  Within minutes I found the pinch point.  See all of the repeated pattern in the third layer from the center?

2014-08-21_07-53-41

Turns out the file /Library/Server/Xcode/Logs/xcs_proxy.log was huge and never rolled over by the logging utility.  I had been using Xcode on this server to run Bots but had since turned it off.  I still need to figure out WHY this file is being written to without the Bots service running.  Because the file is always being written to, the entire thing is backed up every single hour.

Solution:

sudo rm /Library/Server/Xcode/Logs/*

If I find the solution to the xcs_proxy issue, I’ll follow up.

Long-Running MacBook Pro

uptime

I’ve noticed a trend lately – I never shut down my MacBook Pro(s) any more.  Ever since Power Nap came out I tend to just leave my machines running all the time, even if they’re on battery.  Even with boot times being so fast on the SSD retina MBP I just like the fact I can leave everything be.

 

Asynchronous unit testing Core Data with Xcode 6

The WordPress for iOS project had a number of unit tests using Core Data and a custom asynchronous test helper.  The helper used a semaphore in a global scope and a bit of method swizzling to give a wait/notify mechanism.  The problem with this solution was the global semaphore and poorly written tests causing a conflict.  Tests would call the ending wait and previous tests running Core Data would fire off notifies causing a mismatch between the original test and the recipient of the message to pass by the current semaphore.

The solution was to eliminate the global scope and have a semaphore object/instance that could be passed around by the single test.  The more I started designing the solution I realized we should just start using the new asynchronous testing capabilities of Xcode 6.  Xcode 6 / iOS 8 / Yosemite brings us a wealth of new tools to play with including Swift, the newest language developed by Apple.

XCTestExpectation

The newest member to the XCTest framework is XCTestExpectation.  This class encapsulates a single semaphore (of sorts) allowing your test to wait for 1..n things before the test is considered over.  This helps with asynchronous things like AFNetworking, Core Data, and Grand Central Dispatch.  If you’re using a Core Data stack with multiple NSManagedObjectContext instances (background & main for example) then you’re going to almost certainly want to know how to test asychronously.

Creating a XCTestExpectation is quite simple:

[code language=”objc”]
– (void)testObjectPermanence {
XCTestExpectation *saveExpectation = [self expectationWithDescription:@"Context save expectation"];
// ..
}
[/code]

The method expectationWithDescription: is part of XCTestCase and it has a companion method waitForExpectationsWithTimeout:handler: which you call when you’re reading to block the test execution until [saveExpectation fulfill] is called.  Fulfilling an expectation means the expectation has been met and the flag should be flipped for the test that is waiting.  If your test execution never reaches a fulfillment, then your test will fail when your timeout threshold is met.

Some important things to note about XCTest asynchronous testing:

  • A XCTestExpectation instance can only be fulfilled a single time.  Use multiple instances if you have more than one expectation.
  • Only a single waitForExpectationsWithTimeout:handler: can be active at any one time.
  • Unit tests, by default, run one at a time and not in parallel.  If you modify the test suite running to parallelize, I can see things breaking fairly quickly.
  • There are convenience methods to create expectations on a KVO property or NSNotification

Core Data Secret Sauce

There are a bunch of waits you could fire off a fulfillment on an XCTestExpectation when a Core Data context saves.  In the case of WordPress-iOS we use a central class, ContextManager, to help manage all of the Core Data levers and knobs.  There is a companion class called CoreDataTestHelper that does a bunch of useful things like overriding our persistent store to be in memory rather than on disk and also swizzle a method on ContextManager to fire fulfillments if an expectation is recorded.  Here’s an example of a test using this expectation helper:

[code language=”objc”]
– (void)testObjectPermanence {
XCTestExpectation *saveExpectation = [self expectationWithDescription:@"Context save expectation"];
[CoreDataTestHelper sharedHelper].testExpectation = saveExpectation;

NSManagedObjectContext *derivedContext = [[ContextManager sharedInstance] newDerivedContext];
Blog *blog = [self createTestBlogWithContext:derivedContext];
[[ContextManager sharedInstance] saveDerivedContext:derivedContext];

// Wait on the merge to be completed
[self waitForExpectationsWithTimeout:2.0 handler:nil];

XCTAssertFalse(blog.objectID.isTemporaryID, @"Object ID should be permanent");
}
[/code]

You can see we store the single expectation for the next NSManagedObjectContext save on the CoreDataTestHelper sharedHelper instance. Later on when the context is saved, the following swizzled code executes and fulfills the expectation:

[code language=”objc”]
+ (void)load {
Method originalSaveContext = class_getInstanceMethod([ContextManager class], @selector(saveContext:));
Method testSaveContext = class_getInstanceMethod([ContextManager class], @selector(testSaveContext:));
method_exchangeImplementations(originalSaveContext, testSaveContext);
}

– (void)testSaveContext:(NSManagedObjectContext *)context {
[self saveContext:context withCompletionBlock:^() {
if ([CoreDataTestHelper sharedHelper].testExpectation) {
[[CoreDataTestHelper sharedHelper].testExpectation fulfill];
[CoreDataTestHelper sharedHelper].testExpectation = nil;
} else {
NSLog(@"No test expectation present for context save");
}
}];
}
[/code]

Next Steps

Our asynchronous tests are definitely not finished and the Core Data testing stack will most likely continue to change.  Our service layer doesn’t enforce a single save paradigm – we tell contributors that they should probably save often and at least one time before the service method completes.  The problem with the design we’re using above is that there is no good way to let a number of saves happen and to wait until the very last save.  In order do that, we’d have to offer up a special saveContext method on ContextManager that could get an instance of an XCTestExpectation.  That method would exist only as a class extension in our CoreDataTestHelper.  It’s messy but then again so is Core Data at times.  🙂

Pull Request

The changes I made to the WordPress for iOS project are up for review in this GitHub Pull Request.

Things With Wheels Are Meant to Move, No?

Table

I met some fellow coworkers at Hudson Business Lounge downtown Milwaukee today on a $25 day pass.  I’ve been a member in the past but haven’t been there in over a year.  I sat down and realized that the four of us wouldn’t fit at the table because of that awkward power outlet under the one chair.  I decided to move the table so that it was centered between the chairs.

This is when it all went wrong.

As I started to push on the end on the right pictured above, I realized quickly that physics (as I knew it) wasn’t working right.  Instead of the table top moving parallel to the floor, it started to nose dive forward.  Suddenly I felt a sharp pain in my shin and saw my Kleen Kanteen coffee cup rocket off the table and onto the floor.  The two MacBook Pros looked at me in horror as they gripped on for dear life with the 34 cent rubber pads under them.

Thankfully the MacBook Pros stayed put and only one got kissed with a splash of coffee + soy milk.

That’s about when I realized the table top wasn’t actually affixed TO ITS LEGS.

Table modified

Coincidentally this meshes well wish my previous post about not assuming things were done correctly in the past.  Just because something looks like it works right doesn’t mean it actually does.

The best part is the guy working front desk told me to not feel bad, it’s happened before.

 

Systems Philosophy

I was apparently feeling philosophical the other day and posted two tweets about dealing with systems architecture.  They generally apply to life as well, so I’m posting them here on my blog so I don’t forget them.

Just because something was done a certain way, doesn’t mean it was done right and even if it was done right at the time it may be wrong now.

https://twitter.com/astralbodies/status/488786577360171008

 

Never fear asking questions and challenging even yourself.

Wax on, wax off.

https://twitter.com/astralbodies/status/488786693999558656

Page 20 of 30

Powered by WordPress & Theme by Anders Norén