Three weeks ago I launched iAdd for iPhone, a productivity app which is very important to me. Not only because I coded every single line of it, but because this app is the tangible result of more than 3 years of testing, learning and writing about personal productivity. iAdd is based on my own framework, Assess – Decide – Do. It implements every single concept of this framework, bringing to life a completely new approach towards productivity. This launching thing was also a good pretext for me to understand what it takes to create an iphone app in 30 days.
One thing that you may not know, though, is that 2 months ago I had no idea about how to write an iPhone app. I didn’t know Objective C at all, although I do know a few other programming languages, like PHP, Java or JavaScript. Two months ago I also had no idea that I would actually finish this task and have the app live in the App Store. When I started to work for this project (and yes, it was just a pet project in the beginning), all I did was to log daily my progress. And this is exactly what I’m going to do in this blog post, I will publish these daily logs (in a more or less abridged version of course) giving you a time based description of the whole process, from installing Xcode to having your app in the AppStore.
The Set Up
Warning: this is going to be a highly technical post, so if you’re unfamiliar with terms like compiling, backtrace or ViewControllers, you shouldn’t read it. Alternatively, you could only read the “frustration level” paragraph on each chapter and have some fun. Three weeks after, I still have a lot of fun reading those parts, although at that time all I wanted was to draw many, many little men named Steve Jobs and tear the drawings apart. Slowly. Oh, and nobody could pronounce “apple” near me without triggering an uncontrollable itching all over my head.
There is also a little reward at the end of this post. If you get really curious about the app, there will be a giveaway: I’m giving you 20 promo codes to test out iAdd for yourself. The details are towards the end of the article.
Oh, and the article is more than 7500 words so please set aside at least 15 minutes if you want to read it all. You’ve been warned.
But first of all, some words of caution.
First: I am a seasoned PHP programmer, having written more than 100.000 lines of PHP code. I also had a deep knowledge of some high level frameworks over PHP, the most important being CodeIgniter. SQL or JS were common sense to me too.
Second: I knew the whole app structure inside out before starting to code. In other words, I had a very clear client brief, including the user interface. There were some significant changes made on the go, as you will see, but the basis was there before. In my experience, more than 60% of development time is spent on user interface.
Third: I am obsessed with learning new things. I can also be insanely disciplined and focused on what I do. Sometimes I am close to pathological behavior, and I am aware of that.
Fourth: I have completed all the necessary steps to become an Apple Certified Developer (paper work, paying the 99 USD and all) long before I actually started to work. This post will not cover this process.
***
Now, one may argue that my programming knowledge was an advantage in moving to Objective C and iPhone. There was only one point in which my PHP experience served me well and that was the deep understanding that if you write some code properly something interesting will happen. 🙂 In other words, my prior experience as a programmer didn’t count. Why? Well…
PHP is a procedural language, Objective C is a object oriented language. In PHP you write functions, in Objective C you write classes. Lately, PHP become object oriented too, but the vast majority of apps are still written with loads of procedural functions.
PHP is basically an interpreted language, Objective C is a compiled language. Even more, in Objective C you can send messages to objects at runtime. That means that even if your code compiles without any warning, you can still get some runtime booboos. Weird.
PHP has garbage collections which means your variables are automatically discarded when they are no longer needed, in Objective C you have to do your own management memory. Prepare to read a lot of sentences starting with “Message sent to deallocated instance…”.
Speaking of errors, specifically about error messages, after 30 days of learning Objective C I am totally convinced that the error messages in Xcode were invented by a joyous and careless hermit, with the only goal of driving programmers crazy. Program received “BAD_EXC” message. Wow, really? I got this error at least a few hundreds times and at least half of times I was completely puzzled.
Incidentally, since I started to code in Xcode, “Program received BAD_EXC” is what I’m mentally telling myself when Bianca is completely stubborn and I can’t get away with my normal approach. Ok, Bianca is having a “BAD_EXC”, time to start debugging.
Oh, and the infamous “Message sent to deallocated instance “. You kidding me? Sometimes I even had the feeling that the source code on the editor was forming a twisted and evil smiley. The joyous and careless hermit was smiling at me from behind the whole Xcode fence.
Enough with whining, let’s start this. Let’s see what it takes to write an iphone app in 30 days.
Day 1 – Getting Acquainted With Xcode
Getting familiar with Xcode. Learned how to create a project and what the folder structure means. The folder tree you see in Xcode is not necessarily the same you see in Finder. Can be tricky at times. Did a few tests with some sample projects to see how the building process works. Installed a few apps on Simulator and also in the iPhone. Modified some labels just to be sure they’re popping out modified in the simulator. You know, how to get “Hello World” to display “This label was modified by me in Interface Builder”. Living dangerously, so to speak.
Frustration level (0 – 100): 0 I actually had fun.
Day 2 – Core Data Bed Time Stories
Deciding that I am going to use Core Data for storage. I knew SQL more than better (used to write some haiku’s using left joins and alike) but for some reasons Core Data looked much more interesting. I was attracted by the fact that in Core Data you model your data before implementing it, visually creating the relationships between your entities at the design stage. Once you created the model, XCode will generate the implementation files for your objects. Say you have an object called Task in Core Data, Xcode will take care of the implementation files, so all you have to do in code is to write something like:
task.dueDate to get the due date property of a task.
I also learned three fundamental notions for Core Data, especially useful for those who are migrating from an SQL backend:
PersistentStoreCoordinator, ManagedObjectContext and ManagedObjectModel.
Frustration level (0 – 100): 5 – There was some fog related to how a Core Data model maps a data base and the role of those top level objects.
Day 3 – Creating And Saving Data
Spent too much time with the FetchedResultsController class, trying a simple select from DB. Took me a few hours to understand that FetchedResultController is a class designed specifically to be used with a TableViewController. In other words, if you just want some data pulled out from the DB, and not necessarily displayed in a TableView, you could use a simple fetchRequest. Also, I started to properly use NSLog().
In Objective C there is usually too much overhead to put a label in the interface and assign its value to your test data. If you just want to test some results, NSLog() is a much easier way to do it. It just logs to the console whatever you tell it to.
Frustration level (0 – 100): 15 – That FetchedResultsController was really difficult to understand. Also, I had a little bit of trouble understanding the TableView object, but I eventually got it.
Day 4 – First Withdrawal Impulse
Although I did learned some fancy things, in the 4th day I had my first withdrawal impulse. More on that on the “frustration level” paragraph. As for the things I learned, one of the most interesting was that in Objective C you have to use a LOT of typing, just to concatenate two strings. Have you heard of something like “appendStringWithFormat“? Excuse me, I was used to type a simple dot “.” to make the concatenation. Whatever.
Frustration level (0 – 100): 60 – I installed a fully fledged core data sample app just to have a glimpse of what I was starting and simply got overwhelmed. What am I doing here? I should try something much easier. I’m not up to this challenge. It looked enormous. Too much.
Day 5 – Working Data
It was a long day. I created a first view, in which I was adding some text and then saving it to the database. Incidentally, the first data type was an “idea”, not a “task”. I was saving ideas in the Idea Core Data model. Also, learned how to make a TableView reload. Coming from PHP, when user interaction is almost always necessary and expected, you don’t pay too much attention to other parts of the app. In iPhone programming, you gotta place calls to reloading your data in several places in the app. At this point, I was still following a mental framework of “procedural”, instead of “object oriented”.
During the day I also spent a couple of hours working on another project, a much simpler one. All I had to do was to integrate a C library and call some functions. I managed to compile it, call the functions and log the results. Still undecided if I was going to follow to iAdd project or settle for the simpler one, with the external C library.
Frustration level (0 – 100): 35 – A lot of trial and error and also a lot of writing and deleting. Didn’t actually know where to head because there was too much information I didn’t master. Each improvement was the result of hours of falling down and getting up again. The biggest confusion at that time was the syntax, many errors from improper using or accessing properties.
Day 6 – Detour
Spent the entire day fiddling with the external C library project (I will call it like this, although it’s more than that, hope to have it published in a few weeks too). For some reason, it looked easier. I got some minor results while completely avoiding the iAdd project. Just didn’t think at it. Cleared my head. Got some rest.
Frustration level (0 – 100): 0 – I was like in a one day vacation. Just gave myself some mental space.
Day 7 – First Big Leap
After a day spent in relaxation, I came back to iAdd with significantlyh more motivation. I took a major step forward deciding I would completely rewrite the code. From now on, all database calls were to be placed in a single class. For the more experience programmers that seems like common sense, but as I told you I came from a PHP background. Now you understand why my previous experience almost didn’t count.
I created the class and moved all the Core Data related code in that class. My first approach was to use an App Delegate for it and call it everywhere I need it. By the end of the day I moved all the code there and make sure it worked. Calling the class in other views was problematic, though.
Frustration level (0 – 100): 20 – Meaning frustration was there every 5th minute, if you know what I mean, but at least it was bearable. By starting to organize the app at a higher level I created a bit of light over the whole project. Still unsure where this whole 30 days challenge will lead, but at least something started to get some structure.
Day 8 – Going Singleton
The App Delegate id didn’t look like a viable option so I decided to make my “super data model” class a singleton. Never really knew what a singleton was, if you’re asking me. Never knew what a singleton was if you don’t ask, either :-). So I had to read for a few hours and ponder all the theoretical and practical implications of using a singleton. In the end, it looked like it was the best way to go, although the implementation looked a little complicated (or hard to understand the first time). In the end, this proved to be one of the best design solutions for this project.
After making the “super data model” singleton I implemented a few new functions, especially for the first level of views, the ones that listed the data in the Assess, Decide and Do areas. Was able to use the “count” specifier in order to find the total numbers of ideas, tasks or projects.
Frustration level (0 – 100): 0 – For some reason, the moment I started to understand what I was doing, I wasn’t frustrated at all. Everything was going on in the right direction. It wasn’t going on smoothly in the right direction, I had to maintain a very high focus for several hours, but the end result was incredibly rewarding. Hey, I know singletons! Do you?
Day 9 – First Core Data Disaster
Since I was working a lot with data, I had to make some modifications to the underlying data model (the .xcdatamodel file, namely). In Core Data, if you make modifications to your data model AFTER you started to actually with it, you’re going to be in trouble. Big trouble.
First of all, you’ll have to reset your persistent store coordinator, by choosing another name for the database layer (I’m using sqlite as a back end for Core Data). It simply doesn’t work to just update it, as you would do with a MySQl table, for instance. Basically, that means you’re going to lose ALL your data in the previous data model. I think that was the first time I thought at the word “migration”. A few days later I had to thoroughly deal with all the migration headache, but at that point I was just disappointed with losing my test data.
And as if this wasn’t enough, I had more: if you make modifications to your data model, you’ll have to regenerate all the managed object classes, otherwise you won’t be able to access the new properties or entities you just added. If you have many entities (tables) in the data model that could become confusing and difficult to manage.
So, the day was spent in despair over the lost data and trying to plan as thoroughly as I can the data model future evolution, in order to avoid other changes. Just to feel good, at the end of the day I made some small cosmetic changes to the interface: get rid of some buttons and made the text fields bigger. You know, just to go to bed with the sensation that I actually did some work.
Frustration level (0 – 100): 50 – Losing data is bad. Especially if you’re building an app which is processing data. It’s basically a disaster.
Day 10 – The Consistency Day
I finally had a deep understanding of TableViewControllers and their infamous reloadData() function (or message, in Objective C lingo). Meaning in the day 10 I was able not only to add data in the database, but to delete it and update the interface. It was the first consistency day in which what I did at the data manipulation level was mirrored in the interface. Feeling rather confident, I pushed it even further: I added a new table in the adding area (the one you actually see right now in the app, if you have it) in order to choose what type of item is added: a task, a project, an idea or an event. And it worked. Toldya, a big consistency day. Hard to believe that only 5 days ago I was ready to quit.
Frustration Level (0 – 100): 0 – Nada. Niente. Zero. Zilch. Everything was falling right into its place.
First Big Milestone
After the first 10 days of this challenge all I had was this:
- a working interface prototype: the 3 tabs were pointing to different view controllers: Assess, Decide, Do
- adding data was working in the Assess realm for ideas, tasks, projects. Didn’t add any event yet.
- deleting data was working in the list views
- listing data was working (and any adding or deleting worked consistently)
- all data calls were made in a single point among the whole source code (the singleton class)
- had the first withdrawal impulse (the 5th day)
- had the first data disaster (losing data and updating the persistent store coordinator)
Not much, I agree. By any standards, not a functioning app. Not even remotely. But enough to get me going. So, here we go.
Day 11 – Deep Digging
It was a full day. Loads of working on the data model, implementing new functions and witnessing a few breakthroughs.
First of all, now that I knew how to reset the persistent store coordinator I started to heavily modify the data model. I made only a few fields compulsory. I also updated all the relationships, especially the deletion rules. Core Data started to emerge like a very interesting modeling tool. It takes a while to understand the ins and outs, but once you get a grip of it, it’s incredibly productive. For instance, if you properly set the deletion rules, the inner Core Data mechanisms can take care of a lot of after deletion cleaning for you, saving a lot of typing. Just by setting the right rule in the data model. In the source code you end up with only one line of code, usually the one in which you call the “delete” message on the managed object model.
I also implemented a new view for adding an event. Wrote the code in less than an hour. Now I was having events too. Nice.
I implemented the entity (table) for adding contexts. Wrote the code for adding and editing the context. Used a Modal View Controller for the first time. Not everything was working 100% at the end of the day for the Contexts area, but at least I learned something new.
Frustration level (0 – 100) 25 – Learning something new is always packed with frustration. If it’s not frustration, then you’re not learning something new.
Day 12 – Going On Steadily
I started to write the detail views for ideas, tasks and projects. Everything went smoothly and didn’t encountered any difficulty. Realized that writing code is the easiest thing in programming. Kinda knew it before that too, but this time I realized it in regard to Objective C. Always thought it’s gotta be difficult to write code in Objective C.
I also decided that I was going to implement a new feature: Collections. In the initial set up, Collections weren’t present, there was something else in their current place in the interface (I won’t tell what because I still want to implement this for the next major version). But at this point I realized I will need some storage mechanism for the data, something that will act as a neutral repository. You can assess a lot of stuff but some of this stuff is not that urgent. Put it into a collection and free some space.
Frustration Level (0 – 100): 10 – I started to feel frustrated by the flood of my own ideas. Once I started to understand how certain things are done, I just couldn’t stop imagining new features and new ways of doing it. Not good. Distracting.
Day 13 – Finishing Ideas
That was the day when I was actually finishing the whole “ideas” workflow: adding an idea, listing ideas and editing / deleting an idea. In my approach, an idea could contain many details (imagine a mind map: the name of the mind map is the idea name, but the branches are details, or tasks). Making a task semantically integrated with an idea seemed rather interesting. So, almost 2 weeks after I started I was able to add an idea, to add some details to an idea and to see all of these in some nice tables.
It was also the day when I learned how to add a background color to a TableView. From that day, each realm had a specific color, following the workflow rules: Assess was red, Decide was orange and Do was green. It’s the same principle widely used in transportation regulation: red: you stop and wait (until you finish what you have to assess), orange you decide to move on (or, in ADD terms, you sign the contract with the task or the event) and green: you’re good to go, move on with it!
Frustration Level (0 – 100): 0 – I was feeling light and easy. I think that for the first time I found some logic in Xcode completion rules. And even started to use those completion shortcuts. Got productive, so to speak.
Day 14 – Getting Closer
Another productive day, another new feature: now you could add a single task too, if you want, not only as a detail to an idea. I also added the Collections entity in the data model, which means I had to restart the database clean again. Losing the test data didn’t hurt this time, because I knew it will happen. What was hurting though was a totally unexpected thing: while I was regenerating my managed object classes (after adding a new entity, that is) I accidentally deleted my singleton. My super data class. No way to interact with the data anymore. The functions were lost. A few hours later I was able to restore it from memory (my own memory, that is), but the whole thing was rather unpleasant.
I linked the Decide and Do controller to the Core Data model, meaning I added the functions for querying the respective realms, but since I didn’t have the functionality to actually send the ideas or tasks to those realms, I wasn’t able to see nothing.
Frustration Level (0 – 100) 40 – Deleting the super data model class file is a VERY nasty thing to do. I actually lost all the data related functions and nothing worked. Luckily, I was able to re-write them pretty much the same and in the end everything was ok. But not without some hair pulling (now I’m kidding you, I’m bald 😉 ).
Day 15 – A Working Model
Probably the most productive day so far. I finished the code for adding tasks to projects, sending projects, ideas and tasks to Decide, and also the code for listing the ideas and tasks in Decide. Added to ability to create and send events to Decide.
I completely implemented the Collections functionality: creating a collection, editing a collection and deleting a collection. I also implemented the “archive” functionality, which basically means saving an object to a Collection. Basic functionality was there, but there were a lot of bugs. Will deal with them later, said to myself.
Frustration Level (0 – 100): 0 – Didn’t even have the time to think at frustration. The app was actually growing under my eyes and every hour was bringing in another functionality. I gradually started to spend more and more time playing with the app than writing code. It felt nice.
Day 16 – Alerts!
I implemented the delete code using a UIAlertView. It took around 45 minutes top, including reading the documentation and writing the code. I started to understand the philosophy behind the whole SDK. That shortened my learning paths a lot. Every time I needed to use a new UI control, all I had to do was to read the local Apple doc and look over the sample code. Most of the time, that was just about enough.
Another breakthrough of the day was finishing the whole process: code for sending an app from Decide to Do. Basically, what I had only on paper and in my mind was suddenly reality: creating a task (or idea, project, event), sending it to Decide, and from there the ability to send it back to Assess or forward to Decide. It was just 2 weeks and 2 days since I started this challenge.
It was also the day when I started to actively monitor and use stackoverflow.com. If you’re going to write an iPhone app, I definitely recommend you check out this collaborative project. Chances that your apparently unsolvable question was already solved at stackoverflow are actually close to 100%.
Frustration Level (0 – 100): 10 – And that’s because I had to implement something new (UIAlertViews). Otherwise it could have been close to 0.
Day 17 – Cleaning Up And Getting Fancy
Spent the day mostly cleaning up the code, ditching some old trials (used a TableHeaderView separated nib at some point and that cluttered a little bit both the code and the resources – nib files – in the Interface Builder). I wanted to make the corners of an editing area rounded so half of the day was spent searching how to do it. Proved to be a little more complicated than I was ready to accept, but nevertheless I finished it with the help of a little bit of Quartz Core. Felt somehow special and fancy, mainly because of the name of the new framework: Quartz Core.
I think that was also the day when I started to use my app as an excuse for not going out or as a standard answer at the phone. “Hey, Dragos, could we use a beer, my friend?”, “Nope, sorry, I’,m working on my app, mate…” I know, I should have that beer. I can get pathological, I warned you…
Frustration Level (0 – 100): 5 – That Quartz Core thing proved to be a little bit too time consuming, but in the end everything went well.
Day 18 – More Buttons
Another “interface” day. I decided to use UISegmentedControllers as buttons, not the native iPhone UI buttons. It just looked fancier, although I had a little bit more code to write. I also decided to group the buttons after the table view, in a new place, namely a UITableFooterView. So, the whole day was spending re-writing the interface in each and every place I had some interaction code. And there were a lot of places.
Guess it was the first day when I actually felt bored because I was doing so many repetitive tasks. Replacing a button in one place is a thing, but then propagating the change in 20 different places gets really boring.
Frustration Level (0 – 100) 50 – This time the frustration source wasn’t the lack of knowledge (or usable documentation) but my own decisions on how the interface should look. I realized I already had a significant code base behind me and every change that should propagate in this code base would require from now on a really really important amount of time.
Day 19 – Connecting The Dots
At the end of the day I was able to assign a context to task, an event or a project in Decide. I was also able to promote a task to a project in Assess. The rest of the day was spent in writing down some constraints, or rules about how the app should treat some special cases. I find it very useful to write down what I can and what I can’t do in the app, although I was way ahead in writing code already. But since the boring task of updating the interface was killing me, writing down those constraints gave me the feeling that I actually did something productive.
Frustration Level (0 – 100): 35 – I guess the frustration was generated not only by the interface update, but by the expectations that were started to build up pretty strong. I mean, now I had the app on my iPhone, I could add tasks and sign the contract to do them, the only thing that was missing was a decent listing in Do, and the ability to mark a task as done. Believe me, it was starting to feel really frustrating.
Day 20 – The Working Prototype
Since I already felt the pressure to finish, I spent the day implementing the Do functions. Now I could follow a task from Assess, through Decide, until Do, and even mark it as done. Big breakthrough. The whole workflow was implemented. Of course, the app crashed a lot and then there were a lot of places left in a less-than-a-prototype state, since I was focusing only on finishing the main workflow.
Frustration Level (0 – 100): 35 – The same reason as yesterday: I was feeling the pressure to finish. Just wanted to see something working, but at the same time I knew that there were still a lot of boring work to be done.
Second Big Milestone
After 20 days since I started the challenge I had the following:
- the app was fully functional
- the app was also highly unstable, there were a lot of unexplainable crashes and incomplete implementations
- I was able to: add a task, idea, event or project.
- I was able to edit a task, idea, event or project.
- I was able to send that item to Decide and have it displayed there
- I was able to assign a context and bounding dates to a task or event and then send it to Do
- I was able to see the item in Do and mark it as done.
The most important thing that happened after 20 days, though, was the fact that I started to use the app as a modeling tool for creating the app. Sort of eating your own dog food, if you know what I mean. Since I had the iPhone with me everywhere, every time I had an idea on how to implement something, I was adding it, assessing it, moved it to decide or do and then review it once I was in front of the laptop. It was an incredible leap in speed. In the next 10 days, basically I knew what I have to do because it was already filtered through the whole Assess – Decide – Do framework in the iAdd app. Except for the times when I actually lost all the data. Which was still test data. Again. And again.
Day 21 – Time For Working With Time
I started something that I postponed for a long time: date and time management. For some reason, UIDatePicker seemed like something ugly and difficult to understand. By the end of the day I started to think it’s beautiful, but still difficult to understand. I was able to set the start and ending date for an event and for a task.
Since I was on a roll with dates I thought to give it a try with a predicate for selecting tasks or events between certain dates, something that I needed in the Do realm. If “predicate” sounds strange, think at it like the equivalent of an SQL query, although the concept is a little bit more abstract (you can use a predicate to sort a Dictionary, a Set or an Array in Objective C).
And by the end of the day I also implemented partially the badges count (how many items in each realm) for the tab bars. Nice. But buggy.
Frustration Level (0 – 1oo): 45 – UIDatePicker is still a nasty thing, not to mention that working with time in Objective C is a pain in the arse. You have to subclass Calendars, Time Zones and Time Components if you want to do some fine grained date comparisons. Complicated.
Day 22 – Counting The Bits And Pieces
Since yesterday was a rather difficult day, I decided to focus on finishing some other bits and pieces, so I completed the Soon and Overdue code in Do. Now I had a complete visual implementation: tasks were nicely organized by date in Today, Soon and Overdue. I also cleaned up the buggy code for the tab badges. Now every time I was doing an atomic operation on a task (sending it to another realm, deleting or marking it as done) all the tabs were updated accordingly.
Frustration Level (0 – 100) 10 – I think I had a frustration level of 10 by habit. I was so prepared to get frustrated that I went on by inertia. Didn’t have any reason to be frustrated but I kept a small dose just to keep my frustration engine in shape. I guess.
Day 23 – Limitations
Now that almost the entire functionality was there, I started to notice some limitations. For instance, the table view cells in a standard implementations have only 4 types of layout. If you want something more, you have to create your own table view cells. And of course I wanted something more. I wanted to be able to display the context under a task and the due date on the same line, None of the existing layouts of the default table view cells provided something like this so I started to do my own table view cells. And nothing more, of course, for the rest of the day.
Frustration Level (0 – 100) 60 – Learning something new is always frustrating. Learning something new knowing that you have only 7 days left to finish your challenge can be really frustrating.
Day 24 – Rewriting The Old Code
After spending the last days building new table view cells, I thought it would be nice to actually finish something. So, I took each and every list view in the Do realm and implemented the finishing code for a task (or event). Boring stuff, but pushed me forward. I also implemented filtering in the Do based on tasks or events using a UISegmentedController in the view’s toolbar. In other words, one could see just tasks or just events, or both in every section of Do: time based (Today, Soon, Overdue) or context based.
Frustration Level (0 – 100): 25 – There was an increasing internal pressure for finishing things up which made me quite nervous. I was happy to finish the lot for the day.
Day 25 – New Interface Choice. Again
It may have been the increasing pressure, it may have been a deep desire to make things right, fact is that in the 25th day I realized my user interface sucked. Big time. There was too much real estate consumed by the possible operations you could do with a task (make it a project, delete, archive) and too little for the task itself. So, I decided to hide those operations and make them visible only when the user would touch a standard “Actions” button in the upper right corner. When the button was touched,a standard toolbar would slide up from the bottom, containing the three buttons. Interesting. Only I never worked with a toolbar before. By the end of the day I had it implemented in a view. Still pretty buggy but mainly working.
Frustration Level (0 – 100): 75 – A new interface decision so close to the end couldn’t be felt nice. On the contrary. I admit I was incredibly stressed but somehow the stress motivated me. I knew the decision was good and so the work that came attached was well worth it. That didn’t prevented me to feel like a bird on a cage. Or something like this.
Day 26 – Finishing Big Blocks Of Code
By that time all I wanted to do was to finish the task. Or the app, Or everything. I just browsed through my “Do” realm and implemented whatever I picked first. I added the priority functionality for tasks and completely recoded the Collections section, finishing the partial implementation. I also implemented a migration model for the data model. From that day, no matter how I modified the data model, I didn’t have to reset the database again.
Frustration Level (0 – 100) 50 – A little lower than yesterday but still a constant buzz in my head. But still, this buzz, although it was a kind of pressure, made me focus on the task.
Day 27 – Interface. The Final Frontier.
I decided that I have to put an end to all my interface ideas and spent half of the day pondering what I should leave and what I should postpone. I even wrote an entire document, postponing a lot of functionality for the next major version. For the record, the document was called: Minimum Product Demo, or what is necessary for the product to be functional,. but not perfect. The other half of the day was spent coding. Basically, the app was done in the 28th day. The functionality list was frozen.
Frustration Level (0 -100) 50 – Now I was getting frustrated because I have so many ideas but no time to make them alive. Nevertheless, even at that bare bone level I agreed to stop, there was still so much work to do to bring the app at the Minimum Product Demo level.
Day 28 – Getting Ready To Submit
With only two days before the deadline I realized I didn’t have a settings section. No more arguing or negotiating, I just started to code it. I also added a Help and FAQ section.
Frustration Level (0 – 100): 10 – Now I know that this was the silence before the storm and nothing more.
Day 29 – Solving Puzzles
Bug hunting. Loads of bugs. A lot of hunting. Crashing, identifying the bug, solving it. Restart the process. All day long.
Frustration Level (0 – 100) 75 – When you have only one day to finish and you realize that almost EVERY section have a few serious bugs, you can’t be relaxed. At all.
Day 30 – Calling It A Day. Or An App.
In the final day I was doing a final testing round and bug hunting. Didn’t find any bug and the testing went well. No crashes. (Unfortunately, just after the launch I spotted a crash so I had to come up with a fix pretty fast, in less than a week).
Frustration Level: 80 – The highest ever, because the stress of how the app would be accepted was incredible. Now I was pwerless. Nothing more to do. Just waiting for the reaction. Incredibly stressful.
An Iphone App In 30 Days
After 30 days I had a working app. There were a few critical decisions about what the app should contain in the final stage, but I finally did it. The app was ready, tested, polished and, what was the most important thing, was useful. At least for me. The implication of actually using the Assess – Decide – Do framework in the final stages of building the app were huge. I honestly think that for this complexity level, I should have spent at least twice the time finishing it.
40 Days After
The initial challenge was for 30 days and I met the deadline. I had a working app in 30 days. But in fact, I had to spend another 10 days on tweaks, testing and cleaning up. A lot of cleaning up. I actually started to organize the code, to hunt memory leaks (I could write an entire post only on hunting, finding and eliminating memory leaks. Wait! I guess I could write a mini-book on this topic 🙂 ).
Another time consuming task was making the app ready for submission. Having a working iPhone app is one thing, but having it published in the AppStore is a completely different thing. There are a few distinct steps that you have to focus on.
First Level: The certificate and provisioning part. Please, pretty please, with sugar on top, do read Apple’s documentation on the Provisioning Portal BEFORE making assumptions on how much time it will take. Because, no matter how much time you allocate for it, it will always be twice. I mean it. It’s time consuming, tedious and confusing.
Second Level is the building of the app. You have to be extra careful on what provisioning profile to use it and what version (Debug, Release or Distribution) and specific target are you going to use. Again, Apple’s Developer Center is your best friend. Read on until you get it. May take some time.
Third level: the whole submission process, because it involves a lot of work: your app should be artwork ready. description ready. tags ready. You gotta create a series of icons separately from what you usually see in an app, there will be one for the app and one for the AppStore, different sizes. Must be extra careful when choosing your keywords, because your app is going to be found by those keywords. All in all, once you got the certificate / provisioning ready AND the app build in a proper way, allocate at least one day to have the copy details for the app sorted out.
Promoting An iPhone App
If you’re an independent developer, you gotta take into account the promotion part. The AppStore ecosystem is so crowded that you simply can’t do it without it. I won’t cover the details of promoting my app in this post, it will take too long.
The good news for you, and I mean you, the one who reads this post, is that this whole promotion thing is THE place where you can play a big part too, if you’re wondering. 🙂 Not only you could grab a nice promo code (more on that on the next paragraph), to try iAdd for yourself, but you could also spread the word about the whole thing. How?
You can save this post to delicious, reddit, or StumbleUpon (there’s a small square at the end of the article with links for all those services, didn’t write to clutter your reading with more links 😉 ). What more you can do? You can tell your friends and colleagues about it. You can tell your girlfriend about it and believe me, it will make you look good. If you don’t have a girlfriend, just spread the word about the app and who knows, you may get a girlfriend at some point (statistically speaking, there is a chance). You can even tell your mom about it. Here are a few convenient templates for the telling your mom part:
“Hey, mom, I just got this amazing thing you should check out, heard that Oprah is using one of these too…”
“Hey, mom, remember how you told me I was lazy? Well, I’m not! I’m Assessing! You wanna see?”
“Hey, mom, when’s cousin Bob birthday? You know, I just don’t wanna miss it again. I’ll save it on this… What is this? Well, just a thing that helps me remember cousin Bob’s birthday. Wanna check it out?”
I could go on and on like this forever but I’m pretty sure you got the message.
And if you really, really want to promote the app, now that you know how much hard work it contains, you could just buy it for 0.99 USD. Use it for a few days and then leave a nice review on the AppStore. I’ll think good thoughts about you. Promise.
The iPhone Promo Code Giveaway
That’s the part I was talking about in the beginning of this post. If you want to check out iAdd for iPhone for free and have an US iTunes account, just leave a comment and let me know the following info: the blog you’re running, the main topic of that blog and where are you going to let me know your opinion: on the blog or on the AppStore. There is no obligation to leave a review on the AppStore, by the way, just do how you feel.
I put aside 20 promo codes for this thing and I’m going to give them on a “first come, first served” basis. So, you’d better hurry up, so to speak. Remember, the promo codes are working only for the US iTunes Store.
The 7 Commandments For Writing And Publishing An iPhone App
If there are some basic principles that I could take out of this experience, I would lay them down like this:
1. Think it over. Have it clear in your head BEFORE starting to code. If necessary, do some prototyping first. If you don’t, you’ll get lost in a swamp of complicated Objective C notions and overwhelmed by the whole bureaucratic process of submitting the app to the App Store, to a point where you’re actually forgot what you’re coding.
2. Prepare to face some withdrawal. If you’re an indie developer, having a day job (or a life, for instance) prepare to face some serious rejection in this process. It’s not easy and the withdrawal impulse will come, sooner or later. In my case, just avoiding it for a while and moving my focus towards something else did the trick. Your mileage may vary.
3. Read. Read. Read. There are tons of documentations available on the net. I highly recommend the collaborative project at stackoverflow.com. They’re incredibly well indexed in Google and their search engine is also fantastic. When I was completely blocked, in 90% of the cases, just asking stackoverflow.com in a simple query unblocked me.
4. Subscribe to WWDC. This is a library of video, usually from the event with the same name: World Wide Developer Connection. As a developer, you get access to a huge library of movies and sample code that won’t be available to other developers. I personally subscribed to it a year ago but I only reaped the benefits now, when I actually wrote an app. There’s something very intuitive in watching a movie.
5. Log. Daily. Extensively. If you don’t have a SVN systme in place (I don’t have one at the moment, although I do feel the need for it) you will have to log everything you do. In the first 10 days, I was “coding” for 60% of the time and the rest of 40% I was just logging my progress. Write it in black and white. It will help you tremendously.
6. Test. Test. Test. Maybe the app will look good on paper but bad on the iPhone. Maybe nobody will need it. Maybe there is no need for it so you’d better do a development build, install it on your iPhone, use it, and forget about submitting it to the AppStore. Be sure that somebody needs what you’re doing.
7. Do Write Code. An app will never build by itself. Using high level frameworks (there are quite a few these days) won’t save you for writing code. Interface Builder won’t do the job for you, it will only align some controls on a canvas. If you want to code an app, do write code. It won’t work without it.
One more thing… Of course, I have my “one more thing” too, what would you expect? 😉 As you can see, I logged the frustration level daily and one may argue that this is a negative polarization. That I’m focusing only on the negative side of things. Not true. Not at all. I could have log the level of satisfaction too, but to be honest, on a scale from 0 to 100, this satisfaction level was always at least 120. Sometimes close to 500. I’m not joking. I had an incredible time doing this. And this leads me to the final words for this article (seriously, these are the final words)…
What’s In It For Me, At The End Of The Day?
Beyond the whole Objective C learning stuff, beyond being featured in the App Store, beyond the huge frustration I experienced in this whole process and even beyond the money that I’ll make out of it (or that I won’t make out of it, respectively), there’s something more important that remains. At least for me.
And that’s the feeling of getting better. Of doing something new. Of creating something valuable. The feeling of being fulfilled. The feeling of making a difference. The feeling of overcoming failures and my own limiting beliefs.
At the end of the day, I’m not an Objective C programmer. Not even a personal development blogger. I am nothing but a better human being, free and powerful. So powerful that I can make my dream of creating an an iPhone app in 30 days a breathtaking reality.
And that is a hell of an end of the day, my friends 🙂
Hey, try Swift next time! 🙂 or Java with RoboVM
have a nice one!
Thanks, that Java thing looks interesting 🙂
I’m a Unity user and I have my entire app compiled within Unity already, but had no idea where to start with Objective-C or Xcode, and this tutorial helped alot with starting the process.
Thanks for the awesome information!
Dang Dragos,
Reading your post brought back memories of chasing memory leaks in a previous life. Did you have purify or a program to help you find the leaks? Man that can be painful. Awesome post Dragos. I truly felt your pain and determination
In Xcode there is a helper app called Instruments which goes from objects allocations up to memory leaks and even shows the assembler code. Once you get a grip on it it’s really helpful. There are also various functions inside Xcode, like “Build and Analyze” which are also quite useful.
Thanks for stopping by 🙂
Man, you are huge!
From the setup, I miss the second part, the one with the client perspective. How do you learn that? How do you know what the client wants?
I start with an idea. In this case, my own framework put into an iPhone app. Once I’m at the MPD level (minimum product demo) I launch and wait for feedback. This is EXACTLY where I am now. The app started to generate a bit of buzz and people are writing me back.
Dragos,
I have to admit I skipped all the technical stuff because it may have been another language. What you did state in your conclusion is perfect. It is why we are all on this planet… to be continually evolving and creating grander and grander versions of ourselves. Can’t what to see what is next from you!
I’m glad I had the opportunity to meet and to see how determined you are.
I was surprised to see how you can start from scratch and succeed in doing extraordinary things.
It was very motivating for me.
Good luck!
Tica2
Dragos, although this was technical in nature it was hugely inspiring to see your determination and your energy to succeed. I truly wish you all the best mate.
Dragos, I couldn’t do it in 3 months! You are amazing – if this is not a show of determination and single-minded focus, I don’t know what is! Thank you for sharing in such detail!!!
I’m a PHP guy starting on an iPhone app so your blog was very inspirational, thank you.
I’d definitely like to checkout your app if you wouldn’t mind sending me a code. Unfortunately, I don’t have a blog but I’ll be sure to leave a fair-minded review on the app store.
Wow wow wow. Huge post + sharing experience on your 30 days coding challenge. To be honest, I’ve prolly had no idea how it’s like until I get the coding done myself *chuckles*. But your enthusiasm can be seen in this post and that’s where I find this work great to amazing. 🙂
I too went into the software for the past month and launched what I’d call the simplified productivity apps for the PC (I’m not the coder) with quick apps such as the PC Binary Converter, PC Currency Converter, PC Unit Converter and yesterday just went live, the PC Alarm Clock.
Liked the last line in this post too. We are human beings who are not into becoming the most powerful bloggers or developers in the world, just people chasing dreams and creating great stuff from ideas to breathtaking reality. 😀
Daniel
I would not have been able to accomplish it even with I know PHP. Your energy is inspiring! It is amazing that you are able to finish it in 30 days!! Way to go! Retweeted!