NSOperation – My Story
Finally took the opportunity to watch Advanced NSOperations (Session 226) from this years WWDC. I’m happy to see so many talking about it over the last week. NSOperation and NSOperationQueue along with NSURLConnection and NSURLConnectionDelegate have been the basis of almost all the iOS apps I’ve ever worked on going back to 2009. They were first introduced with Mac OS X v10.5 (Leopard) in 2007. They’re solid, proven and incredibly powerful. It was nice to see a WWDC session re-introduce them to the newer crop of developers, with some inventive uses, since I think many didn’t know they existed or understood how to use them.
My First Introduction
I was first introduced to them through Brent Simmons. Brent had written what I can only imagine was the most powerful and performant RSS downloading engine in Objective-C at the time (who knows, it may still be the best). It was being used in NetNewsWire as well as TapLynx. I was starting on my first iOS app for NewsGator Social Sites and needed much of the same networking and XML parsing so I began to incorporate it through a shared repository Brent setup for us to use.
It worked by creating separate NSOperations for each RSS subscription and throwing them all onto an NSOperationQueue which performed the download and parsing on a background thread then used NSNotificationCenter to tell other parts of the app when a feed was successfully downloaded, parsed and stored.
Social Sites wasn’t just RSS driven but most of the API’s were still XML based so the only changes I had to make were in XML parsing classes and not in the networking logic. Brent had solved that for me. My other change was to write the data to Core Data instead of straight to SQLite which is another story. (I did have a “doh!” moment when watching the session and seeing a separate save context operation dependent on all the other ones completing. That’s a great idea).
As Social Sites grew I needed more networking capability. I had to download not only messages being shared on the system but also users profile pictures and other meta data that was associated with a message but not as important to the user as the message its self. NSOperation already had priority setup so it was dead simple to throw user image download operations onto the queue but allow content downloading to execute first.
The same engine also powered networking for Glassboard iOS but with a new JSON parser instead of XML. That was the only change that I can recall being needed to reuse the entire background networking engine. Everything else was already done.
My Current Affiliation
After leaving NewsGator I started to see projects that used AFNetworking. This was before NSURLSession was introduced. AFNetworking at its heart is the same as what Brent had written. I had much appreciation for both once I realized that.
When I started on the current project that I work on I saw that it used AFNetworking but used a block approach to networking calls as they finished as opposed to NSNotification. To be honest I was a bit torn. I liked the block approach since it wasn’t as disjointed as NSNotifications. You could see who executed the network call and how it handled the result. But it was also very messy and added tons of code to the view controllers needing the data. It didn’t feel right but with so much code in place, an existing large team of developers and features outpacing refactoring it had to stay.
As the project moved on though we started seeing places where we had the same business logic being duplicated on different view controllers. Duplicated code is duplicated bugs so we started looking into ways to fix it.
What was introduced was a CommandBase class based off of Command Pattern popular in other languages. Of course my first reaction was “This is an NSOperation”. I was then pointed to a GitHub project by Magical Panda called MGPCommandBus which I pointed out was just an NSOperationQueue. (It may be more, I don’t know, I didn’t explore it any further then the description).
Unfortunately I was overruled with the thought that this simple CommandBase was better then the “overkill” of NSOperation. Don’t ask.
What I found more intriguing though is after introducing the pattern to the team how aptly they applied it in some very interesting ways. We started using commands not only to do networking but also doing things like deep linking, checking permissions for device hardware, even supporting a multistep upload and checkout process. It was great to see the size of our VC’s shrinking while making business logic independent, reusable and testable. I think iOS developers understand NSOperation they just don’t know how to successfully use it.
When I wrote my sample app for my talk at iOS Dev Camp Colorado Springs on PassKit I decided to try my hand at NSOperation again to do the networking with NSURLSession and data parsing with NSJSONSerialization. You can see some samples of what I did with my SignInViewController and my FetchAccountOperation.
Watching the WWDC Session tonight has me thinking that this pattern is finally validated in my head.
My Future Affiliation
I’m guessing some will say that this type of architecture is not necessary in Swift. I can’t say one way or the other if they’re right. I can read some Swift but to say I could architect an app solely in Swift at this point would be a lie.
What I can say is that I tend to learn languages by seeing them used to solve problems that I already understand. The demo app from the Advanced NSOperations session is all in Swift. I plan on using it to teach myself more of the language while knowing what its trying to accomplish.
I’d like to thank Dave DeLong and all the others that contributed for the great session. I gave it a standing ovation from home when it completed 🙂
Also questions, comments telling me I’m wrong are always welcome. As someone I respect told me last week at WWDC – “It’s the internet. Everyones allowed to be wrong”.