Why So Serious?
This is a post that has been sitting in the back of my mind for many months now. I originally conceived of writing this back in February of 2011 but decided that the time was not right for it and waited. Had I written it back then I suspect the text would have been quite a bit different.
I was part of the original development team that wrote “The Daily” for News Corp.
When “The Daily” was released, we expected some issues with it. Every developer should expect issues with a 1.0 release. We knew that it was written under a tight deadline and that there were most certainly sharp edges that we had not identified. The application was about as well received as we could expect from the user base. Some people do not like Rupert Murdoch. Some people do not like his teams slant on the news. That was expected. He is good at polarizing his readership.
The response we got from the developer community was a complete surprise.
## Back In The Day ##
One of the things that originally attracted me to being a Mac/Cocoa developer was the community. I remember, fondly, watching two direct competitors sitting across a table from one another trading code solutions. Both knew that the other person was going to add it to their code base and they shared that information anyway. Both developers knew that it was the other developer that was driving them to make a better product. There can be no first place without a second place. Having a close competitor helps drive us forward.
Likewise, going to a CocoaHeads meeting you would see senior developers, developers who have been doing this for decades, sitting next to developers who are just now wrapping their heads around retain/release. They weren’t pained but instead looking upon the younger developer with the fondness of remembering what it was like when they started. Perhaps a bit of envy of all the exciting things this new young developer is about to learn.
## Introducing The iPhone ##
When the iPhone was introduced we were all very excited to start working with it. Cocoa on a mobile platform! We could not wait to get our hands on it. The community embraced it immediately.
At first you had to hack your phone to write code for it but we quickly got an SDK. The community consumed that SDK with a hunger. The forums were active, the boards were active, the blogs were hot. Everyone wanted to share the new cool thing they learned or share the pain they just went through so that, hopefully, no one else had to go through that pain. The community was alive and prosperous.
I do remember many conversations about what would happen to the community with this sudden influx of developers. Many conversations started over what to do about these developers invading our platform. When I was involved in those discussions my response was always the same; we would welcome them to the community and teach them how we work. We would show them how great it is over here and that we share our toys. We would welcome them knowing that they would become part of us; not the other way around.
For the most part that is what happened. A large portion of these developers joined us. They shared; many new blogs started up, new books were written and our NSCoder nights and CocoaHeads meetings grew. The community became stronger with this influx of new developers.
## A Disturbing Trend ##
More recently, perhaps within the last year, there has been a disturbing trend in the community. Surprisingly, sadly, this trend has not come from the new developers but from some of the older grey beards. There has been a trend to “piss on” things written by other developers. A new app comes out, good or bad, and the claws come out. People are quick to blast it; the more press it gets, the more it gets blasted.
A new photo sharing idea that got a lot of VC money? *Blast it!*
A new game concept? *Kill it!*
An old idea rehashed in a new way? *Destroy it! Burn them!*
He got more press than me? *He must die in a fire!*
I would almost expect this from new developers who just joined the community. However it is not the new members of this community that are all aflame. Most likely they are looking at these ideas and seeing how they can apply them or if there is anything to learn from them.
Sadly though, it is the older, established, members of the community that are turning so hostile. Gone is the sharing and the live/let live attitude that once made this community so great. Quite a few members are just full of piss and vinegar.
You can say what you want about me. I do not hold myself above others and know that my code sucks more often than not. I tend to share that opinion of my code often. I do not share what I have learned to gain glory but to just enjoy the act of sharing. Sharing makes me feel good.
What saddens me is this new desire to attack things that are either new or just in the media. Does the application suck? Maybe. But to curse the developers who wrote it? Not cool.
We as developer must remember that we are **not** the target for 99% of the software that is written. We are not the final judge on what will or will not work. If anything, we are the last people that should have an opinion on what is good or bad. We should be the ones that step back and watch what the “normals” do with it. **They** determine the success or failure; not *us*.
## Some Thoughts From The Trenches ##
Not everyone who reads this blog is an independent developer. Not everyone who reads this blog writes code to fit someone else’s goals so I would like to share a few points from someone who is an independent developer and writes code to meet the expectations from others.
### Deadlines are a bitch ###
Rarely do I have the opportunity to set my own deadlines. Companies who hire development shops almost always have a deadline in mind before the first line of code is ever written. More often than not, they have a deadline in mind before they have all of the requirements defined.
We, as developers, do not get to move those deadlines without massive and dire consequences. Usually our only opportunity to move them is at the beginning and then by saying “No, Thank You” to the project. Moving a deadline mid project usually has financial consequences.
### Non-Developers Think This Is Easy ###
Non-developers see that one new feature as trivial. They see that crash as obvious and do not understand what the hell is taking so long. Business people are non-developers. The people who sign checks are business people.
To go along with my point about deadlines, getting paid involves meeting the requirements of the project within the deadline. These are almost always at odds with each other. The requirements are far greater than can be fit within the deadline. The response from the business team is “add more people, make it happen”. We as developers know that adding more people will actually slow things down.
### The First 90% Is Easy ###
Developers frequently look at a problem and in their first blush say “oh I see how that works, that is *simple*”. That is a trap my friends. Everything looks easy at first. My favorite recent example is the carousel of The Daily. It is trivial right? No, there are a huge number of dependencies and features and bells and whistle and edge cases that all work their way into that piece of the application. The core of moving images around on the screen is trivial. Anyone can do it in a couple of hours. However to complete all of the requirements? Months of work. Personally I am still not completely happy with it. Maybe with 6 more months of polish it will get to where I would like to see it.
Never underestimate the requirements that go into a piece of functionality. Don’t assume that the developers are incompetent if it doesn’t work or perform the way you expect it to. Chances are that there are requirements that you as a user are unaware of.
### Software Development Is Not The Only Cost ###
This is my one hostile point in this post. Whoever thought the iOS developers got paid $30 Million on “The Daily” is a moron.
“The Daily” is a **lot** bigger than just writing iOS code. There is a huge editorial staff, there is a server team, there is office space, hardware, travel, the list goes on and on. The actual iOS code was a small fraction of the huge effort that was put into creating a digital only daily newspaper; the first of its kind by the way.
### Doing Something First Sucks ###
Unless you are trying to get into some record book, the person who does something first is rarely remembered. He who does it best is often remembered fondly. When you are the first to do something you rarely are the best at it. This is just a simple fact of life. When you are the first to do something you are making shit up as you go along. You are guessing. You have no clue what is going to happen when you release. The first MP3 player? Shit. First Tablet? Horrible.
Being first means that you are going to be superseded. Either by improving on your design or by being replaced by another team that took your idea and ran with it. The iPod blew away the first MP3 player. The iPad blew away the first Tablet. I look forward to seeing who becomes the greatest digital only daily newspaper on a tablet. Maybe that will be The Daily via iteration or maybe it will be someone else.
## Conclusion ##
“Be excellent to each other” — Bill & Ted’s Excellent Adventure
This should be the guiding principal of the Cocoa Developer Community in my not-so-humble opinion. It is one of the things that make it great. New people are welcomed and the older members are honored.
There is no reason to hate other development efforts. It does not matter if that developer is better or worse than you. It does not matter what that developer wrote. There is plenty of room for all of us.
Be excited by his or her success. His or her spotlight does not put you in darkness.
I look forward to seeing each of you next week in San Francisco. If you see me please feel free to say hi.
WWDC is once again upon us; be excellent to each other.
SecurVid HD [Advertisement]
This is a short introductory article to welcome a new application to Zarra Studios.
We are involved in a lot of contract work and frequently our clients will give us video files. These files can be demos, mock ups, advertisements, etc.
As a developer on the move, I like to keep these with me and on my iPad so that I can review them whenever I want.
Of course, Client A does not want Client B to be able to accidentally see their files. Lawsuits happen that way.
To make this even more fun, everyone wants to borrow your iPad. Everyone wants to touch it and play with it. This increases the risk of the videos getting into the wrong hands.
From this, SecurVid was born.
## Features ##
SecurVid is designed to put videos behind a password lock. The videos are kept encrypted on disk and are not backed up to your computer that you sync your iPad with. This means that it is not designed to be a storage system for your videos but a protection for videos you need access to but don’t want everyone who borrows your iPad to see.
SecurVid has a lossy way to reset its password in case you forget it. Enter the wrong password three times and it will offer to reset for you. However that reset comes at a price; it will first delete all of your videos before offering to reset the password.
Once you are into SecurVid you can watch the videos you have already loaded naturally. You can also add more videos via iTunes as well as from any other application that is configured with file sharing. Therefore if a client emails you a video you can tap and press on the video file in mail on your iPad and load it into SecurVid.
Likewise you can export videos from SecurVid either for emailing or for loading into another application. You can even mark a video as “unprotected” and allow iTunes to see it next time you plug in your iPad.
## The Future ##
This is the 1.0 release of SecurVid and has the core features that I/we needed in the application. However it is just the beginning for this application. As the application matures we will be adding additional features and continuing to release updates.
## Cost ##
Because the 1.0 has only the core set of features we are offering it at an introductory price of $4.99. That price will remain until the next set of features are added. When that occurs we will increase the price up to the next appropriate level. However if you bought the 1.0 you will get these upgrades for free.
SecurVid HD is available on the App Store now.
Passing around a NSManagedObjectContext on iOS
**This article is reprinted from the MDN**
The documentation on Core Data for the iPhone has lead to some confusion about how best to use Core Data on a Cocoa Touch device. One particular section seems to be the most confusing, specifically:
> A view controller typically shouldn’t retrieve the context from a global object such as the application delegate. This tends to make the application architecture rigid. Neither should a view controller typically create a context for its own use. This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.
> When you create a view controller, you pass it a context. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.
The idea behind this section is the issue of rigidity. Ideally, each view controller should be an island on its own. It should not rely on its parent, nor should it rely on the Application Delegate. Once a view controller is pushed onto the screen it should ideally be its own master.
## Why Rigidity is bad
It is fairly common when designing a Cocoa Touch application to “hard code” everything. Take the following navigation controller design:
![Navigation Controller Design](https://www.cimgf.com/wp-content/uploads/2011/01/Image1.png “Standard Navigation Controller Design”)
When this design, it is common to code each view controller and make it “aware” of its parent. In that design, it would be common to see view controller B call methods or call back (to its delegate) view controller A. While there is nothing technically wrong with this design, it is very rigid. It is nearly impossible to either move view controller B to another location in the stack or to reuse view controller B somewhere else. This is the trap that the documentation is trying to help new developers avoid.
## Solution One
Again using a standard/normal navigation controller design, it is expected that the detail flows from left to right. The left most (or root) view controller contains the most vague information and the right most (or deepest) view controller contains the greatest detail.
![UIFetchedResultsController](https://www.cimgf.com/wp-content/uploads/2011/01/Image2.png “UIFetchedResultsController”)
In this case then the best solution is to use a `UIFetchedResultsController`. This controller can be considered a thin layer between the view controllers and the Core Data bits. The advantage is that the `UIFetchedResultsController` is designed to work with tables. The other advantage is that your least detailed view (the root most likely) can listen as the delegate of the `UIFetchedResultsController` for changes and update itself.
In this design, however, instead of passing around a context, you would hand off just the entity that the child view controller needs to know about. The Core Data Recipes example provided by Apple illustrates this design quite well.
How does this break rigidity? Each view controller, from the root on down, only knows what is passed into it. The root gets the `UIFetchedResultsController` passed into it. The child views only get the items it cares about passed into it. None of them care what their parent view controller is. There is no call back to a parent.
## Solution two
What happens when we don’t have a typical navigation controller design? Perhaps a child view can pop up a modal view that displays different information. Perhaps a child view, for whatever reason needs to access information that cannot be directly passed into it every time.
In these cases there are a few different options.
### View already has a `NSManagedObject`
Following our example above, lets say that view controller C needs to create a new object. Perhaps it is a detail view of a recipe and the user wants to add a new recipe type (perhaps she is a vegan and just discovered there is no vegan type in the list). In this case we have passed in an entity (the recipe) but not a reference to the `NSManagedObjectContext`. Fortunately this solution is easy to fix. The `NSManagedObject` retains a reference to its `NSManagedObjectContext` internally and we can access it. Therefore we can easily retrieve the `NSManagedObjectContext` from the `NSManagedObject` and create the new Type entity and pass it to the modal child or whatever our design calls for.
This again avoids rigidity because the view controller that represents the entity does not need to call up to a parent object or the `UIApplication` delegate. It is self contained and only manages view controllers that are down stream from it.
### View does not have a `NSManagedObject`
In this situation things are *slightly* more complicated. In this case we want to create a `@property` for the `NSManagedObjectContext` and require that our creator set the property.
@interface MyViewController : ViewController
{
NSManagedObjectContext *moc;
}
@property (nonatomic, retain) NSManagedObjectContext *moc;
@end
Again, the view controller is an island of its own because it does not care where that `NSManagedObjectContext` came from. All it knows is that it is required for the view to function. It does not care of it is a new `NSManagedObjectContext` specifically created for its use (perhaps for a cancelable edit tree) or if it is the same `NSManagedObjectContext` that has been passed around since the launch of the application. All it knows is that it has the elements it needs to perform its function.
By making the `NSManagedObjectContext` a settable property we can also transplant the view easily. If, at some point in the project lifecycle, we decide that it makes more sense to have the following design:
![Modal View Controller](https://www.cimgf.com/wp-content/uploads/2011/01/Image3.png “Modal View Controller”)
Taking from Apple’s Recipes Application, perhaps we decide that moving from the table view directly to the image of the recipe is more pleasing to the users and that when they want to see how to make it they can “flip” the image over and see the detail.
Making this change with each view controller being an island is quite simple. We just rearrange the views without having to worry too much about breaking the application.
## Solution three
Up until now we have been looking at just a navigation controller design. But what about tab bars? In the situation of a tab bar we again want to avoid rigidity because it is even more common that tabs will get moved around.
The solution to this is to again use a `@property` for the `NSManagedObjectContext` and require that the creator set this property before the view is displayed on screen. If you are creating the tabs in code this is trivial because you are already calling init on the view controller and you can add one more line of code after the init to set the property.
If the user interface is being developed mostly in Interface Builder it is slightly more tricky. Personally I am not a fan of creating navigation controllers or tab bar controllers in Interface Builder. However if that is the design then I would recommend referencing the view controllers as properties and passing along the context upon initialization of the application. It may be possible to do this entirely in Interface Builder but I am not comfortable enough to recommend that as a solution.
## Conclusion
The overall idea behind this article is to keep each view controller separate from anything up stream or in a different silo. This will make the design far more flexible in the long run. Any time that you feel the “need” to pass in a parent view controller to a child view controller, reconsider the design. Consider using a `@protocol` delegate design or NSNotification calls instead. Keep each view controller as its own private island.
iPhone DevCon 2010
Just finished with the iPhone Dev Con 2010 in San Diego and it was a very pleasant conference to go to. The organizers definitely have a nice balance and treated the speakers well. I enjoyed the trip and I hope that everyone who attended my sessions got something out of them.
As I promised in the sessions, here are the slides and sample code.
* [NSFetchedResultsController](http://cimgf.s3.amazonaws.com/NSFRC_iPhoneDevCon10.pdf)
* [Importing and Exporting Efficiently](http://cimgf.s3.amazonaws.com/Import_Export_iPhoneDevCon10.pdf)
* [Importing Example Code](http://cimgf.s3.amazonaws.com/Import_Example.zip)
And the ZSContextWatcher is located in our [open source git hub project](git://github.com/ZarraStudios/ZDS_Shared.git).
Thank you to all of the attendees for having me and I look forward to seeing everyone at the next conference.
Call for Papers
I remember when C4 started, the first year was a huge amount of excitement. There were going to be people at that conference, speaking at that conference, that were legends in the Mac community. The idea of being able to hear them share the secrets to their success was simply invaluable.
I regret missing that first C4 conference.
In December of this year is another opportunity for that first. The guys who put together the 360 iPhone conferences are taking the plunge and putting together a Mac conference this December. Who is going to be there?
**That is the really cool part!**
They are doing a [call for papers *right now*](http://www.360macdev.com/call-for-papers/). You can be a part of the first experience of this brand new conference. You can help make it great and make it a must attend conference.
I have submitted my paper to speak and I know I will be attending even if I do not speak.
Will I see you there? I hope that I do.
Core Data and Encryption
Just a quick post to point out a great article written by Nick Harris of NewsGator fame. He has looked into the issues with Core Data and encryption.
Core Data and Enterprise iPhone Applications – Protecting Your Data
It has always been a difficult question and fortunately Apple has addressed it for us. Even better, Nick has shared the code so we don’t even need to try and discover the solution ourselves.
Thanks Nick!
WWDC 2010 T-Shirts
In celebration of the late notice of WWDC this year; CIMGF is offering late notice on our T-shirts!
In previous years I took orders and then delivered them to you at WWDC. I discovered something from that it. It was a huge pita for everyone involved. Therefore, this year I am going to do it differently.
I have created a storefront on SpreadShirt where you can order one of several different T-shirts (and a jacket) for this year’s WWDC. The new shirts include the new CIMGF logo which will soon adorn this beloved site.
I hope to see many of you wearing the T-Shirts this year in San Francisco!
My current Prefix.pch file
I have posted and discussed this file a few times but as with all things it has been touched, tweaked, and generally improved upon.
In this article we will discuss the latest iteration of my `Prefix.pch` file. As with anything I post, it is available for you to use as you see fit.
## The File
For those who don’t want to read the entire post, here is the file:
#ifdef DEBUG
#define DLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#define ALog(...) [[NSAssertionHandler currentHandler] handleFailureInFunction:[NSString stringWithCString:__PRETTY_FUNCTION__ encoding:NSUTF8StringEncoding] file:[NSString stringWithCString:__FILE__ encoding:NSUTF8StringEncoding] lineNumber:__LINE__ description:__VA_ARGS__]
#else
#define DLog(...) do { } while (0)
#ifndef NS_BLOCK_ASSERTIONS
#define NS_BLOCK_ASSERTIONS
#endif
#define ALog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#endif
#define ZAssert(condition, ...) do { if (!(condition)) { ALog(__VA_ARGS__); }} while(0)
This does not *replace* the Prefix.pch that comes with your project but it does go at the top of every project that I work on. The rest of this post we will review what this does.
(more…)
Creating a NSManagedObject that is Cross Platform
An interesting question came up on Stackoverflow today so I decided to expound upon it in a short blog post.
A situation that I believe we are going to be seeing more and more often is one where application developers are writing multiple “versions” of their applications to be used on the desktop, their iPhone and now the iPad.
Because of that situation, it is becoming even more important that we write as much portable code as possible. Fortunately, our model can be completely portable between the two platforms.
The PragPub Magazine
Last month I was given the opportunity to write an article for The Pragmatic Programmers great magazine called “PragPub”. I am happy to say that the article I wrote for them was published in this month’s edition. The article, titled “Touching the Core”, is a walk through Apple’s great addition to the Core Data API for the iPhone.
Specifically this article walks through using the NSFetchedResultsController and some best practices in its use. The magazine is available for free on their website, [The Pragmatic Bookshelf](http://pragprog.com/magazines).
Automatically save the dSYM files.
For those not aware, when you compile an Objective-C application, whether it be for the desktop or for Cocoa Touch devices, the debugging symbols are stripped out of the binaries. Therefore, unlike other languages such as Java, when a crash occurs, there is virtually no way to determine where the crash occurred. However, when the applications are compiled, a dSYM bundle is generated. This bundle allows us to match up the debugging symbols with the application’s crash log to help determine the cause of the crash.
Voices That Matter Conference
October 17th and October 18th of this year, the Voices That Matter conference will be occurring in Boston. I will be speaking at this conference on the subject of Core Animation. In addition to myself, there is a very nice list of speakers at this conference including Aaron Hillegass, Daniel Jalkut, Fraser Speirs and many others.
Early Signup
Currently, you can get $200.00 off the the price of the conference if you sign up before the 12th of September.
In addition, if you use the speaker code ‘PHASPKR’, you can receive an additional $150.00 off the price. That is a combined discount of $350.00 if you sign up before September 12th.
http://www.voicesthatmatter.com/iphone2009/
MacBook Pro looking for a good home
Having finally decided that I prefer the 1920×1200 display of the 17″ Macbook Pros I am finally committing to one size of laptop. To help force myself into that commitment I am going to be selling my gently used late 2008 15″ Macbook Pro.
The specs are:
* 2.53 Ghz Intel Core Duo
* 4GB RAM
* 320 GB Harddrive
* 512 Nvidia Video cards (9400 and 9600)
* 2 USB
* 1 FW/800
All of the original hardware and equipment are included.
The asking price is $1,800.00 plus shipping.
The machine is in perfect condition as shown in these photos on flickr (http://tr.im/kQ11).
If you are interested in this machine please contact me at marcus at cimgf dot com.
Core Data and Plug-ins
Thanks to the ability to have configurations in a Core Data Managed Object Model and being able to save data to multiple Persistent Stores, it is possible to have a Core Data Model that is constructed from not only an internal model, but from the models of all the plug-ins that are loaded into the application.
In this example we are going to build a basic application with the following requirements:
- A plug-in framework
- Plug-ins can extend the managed object model of the application
- Removal of a plug-in should not corrupt the persistent store.
WWDC 2009
I am happy to confirm that I will be at WWDC this year in San Francisco. I am making this trip a little tighter, time-wise than I have in the past so I will be arriving on Sunday, June 7th and leaving on June 13th.
I normally post my nighttime plans on twitter (@mzarra) so if you are interested in having a chat then that is the best way to track me down. I will also be tweeting which sessions I am going to throughout the day.
I look forward to seeing everyone there, it should be very interesting as always.