The other day, my father asked me how to get started developing for the iPhone and iPad. He is looking for a technical hobby that he can do while he travels in his upcoming retirement. I had no idea really how to get started so I asked around. I learned quickly that it doesn’t take much to learn if you have an Apple computer.
All that I did is:
Download XCode 4 which is a free download from the Mac App Store.
Of course, this was a very simple iPhone application that was built with only about three ours exposure to Objective-C (the programming language), Cocoa Touch (the iOS framework), and XCode (the integrated development environment). It was a fun exercise. However, if you are only familiar with .NET and/or Java there are some uncomfortable moments with the Object-C syntax that you are bound to encounter. Mind you I am a complete novice with the language, the framework, the development environment, and the platform. Nevertheless, these are my experiences.
First things first… The iPhone application makes heavy use of the model-view-controller (MVC) pattern. I like this. I am familiar with the MVC pattern and I can work with that. What was surprising is that the only code I really touched was the model objects and controller objects. The view was entirely created with the visual designer which generated a storyboard file to describe the view. This file is an XML file. This wasn’t difficult to get used to as I only really worked with the native Cocoa view objects. I am curious to find out what the story for creating your own view objects is.
After dragging and dropping controls on the storyboard, I started working with the controller. This experience was mostly clicking and dragging connections from the visual designer to the controller source code and implementing a few properties and methods. Take a moment to review the controller header file:
Even with some exposure to C and C++ over a decade ago, this header file appeared strange to me. It’s purpose is similar to C or a C++ header file as it serves to declare class, type, function, and constant declarations.
Now look at the source file:
This is the source file which contains the implementation details of the declarations in the header file. There really is a lot going on in both of these files that are needed to compile the view controller.
To be honest, at first glance I was really confused and it took me some time to understand the high level basics of the syntax and what it was doing. The @notation did not make sense. There are many keywords here that don’t translate directly to C#, or Java. I didn’t understand what the dash (-) in front of method declarations and implementations was for. What was the difference between the @interface structure in the header file and source file? I was really lost. The syntax was extremely foreign. Did you notice all the square brackets?
The header file is small and concise and is not too hard to understand. The first think you should notice is the #import directive. This directive is similar to the using keyword in C#. It tells the compiler that you want to include code defined somewhere else in your header. In my header file, I am telling the compiler to include the UIKit header file where the interface of the UIViewController class is declared.
The @ symbol indicates a compiler directive. The interface directive is used to presents the class name (CalculatorViewController) and begins the declaration of the class interface. This should not be confused with the concept of an interface in C#.
It is my understanding that the declarations made in the header file are accessible to other header and source files when they are imported. So in C# terms, you can think of these declarations to have the public visibility modifier applied to them.
@property (weak, nonatomic)
The property directive is a convenient way of declaring a property backed by an instance variable. The closest think I can think of is a the declaration of a property in a C# interface like this (even though it is a really far stretch):
The next thing are the custom options contained in the parenthesis. These options define how the accessor methods behave. If you want to find out more, check out the declared properties documentation.
This directive is used to close other opening directives. In this case, it closes the @interface directive.
Concepts in the Source File
Here we see the #import directive again. In this file we have two of them. The first is the header file for this source file. The second is the header for a Calculator class that is used in the controller.
Again we see the interface directive. This time it is followed by parenthesis. I have no clue what these are for yet. Again my understanding here is that the declarations in this interface block are only visible to my implementation in this source file (somebody please correct me if this assumption is incorrect). Nothing really new here besides those things I don’t quite get.
Within this interface I declare two more properties and introduce some more custom options. I suppose these would be how you declare private properties in C#. But again it is a really far stretch that is not an accurate translation.
The implementation directive is similarly structured to the interface directive as it begins with the presentation of the class name. The difference is that this directive contains the implementation details of the class. It is closed with the @end directive at the bottom of the page.
The synthesize directive the implementation counterpart to the @property directive. This directive tells the compiler to generate the setter and getter methods for the property according to the custom options presented in the interface declaration. In addition, we can also specify the instance variable that backs the property.
What the heck is this? Tons of stuff going on here. What you have here is the pattern of a method prototype. It starts with a dash (-) or a plus (+). The dash makes it an instance method while the plus makes it a class method (or a static method). In the first parenthesis we present the return type. This is followed by the method name interlaced with parameter types and names. I found this very hard to read at first. But with a little practice you can get some really readable methods.
When declaring a method with in the context of the the @interface directive you would terminate it with a semicolon. By contrast, within the context of the @implementation directive it is followed by an open curly brace, the method body, and terminated with a closing curly brace.
For instance, take a look at this method:
This method specifies the getter method for the calculator property. Yes, the compiler would have created a simple getter for the calculator property since I used the property and synthesize directives. But since I implemented the getter, the compiler will only generate the getter method. But moving on to talk about the method. Here I am declaring an instance method that returns pointer to a Calculator object. The method name is “calculator”. This is followed by curly braces that contain the method implementation details.
A loosely translated C# equivalent might look like this:
I added the auto setter in the translation to give you an idea of what the @property and @synthesize directives did for me in this source file.
Let’s look at one more method in the source file:
This example method takes a single parameter. And may be loosely translated to C# like this:
You will notice the return type here is void and that is because the IBAction return type is a constant in the UIKit that the compiler translates down to void. The constant is used for integration between XCode and the Interface Builder tools. I probably don’t have this right either, but it is my understanding at this time (again if I wrong please point it out to me).
I’m sure you are asking about these now. The brackets are another notation that just did not make sense to me until some discussion in the Stanford lecture discussed them and even then I had to do a little reading in the documentation. The bottom line is this is the syntax for sending a message to an object. You can also think about this notation invoking a method.
So there you have it… my first experience with Objective-C, Cocoa, and XCode. I have much more to learn, but I am really happy that I tried it out. It was fun working with something new. I am still curious about how refactoring will work and I am sure I will miss my ReSharper features (if I do get into this I will probably try AppCode). I am also interested to investigate the unit testing options available.
Following my recent post about getting started with RavenDB, I decided to work on a small shopping cart demo application based on the sample depot application that is written in part 2 of Agile Web Development with Rails when I started running into some trouble with the RavenDB auto generated document identifiers and the MVC routes. Like any other programmer, I quickly performed a Google search to see what others had done. The search led me to a few Stack Overflow well voted answers all leading me to a blog post on this topic. Problem solved right? Not exactly. Two solutions were proposed. But before getting into those, I want to describe the problem a little more.
The Problem Described
Take a look at the ASP.NET MVC 3 default route found in the Global.asax.cs file:
This default route will basically allow you access to a resource using the basic URL convention that may look something this: http://localhost/products/edit/1 . However, the default RavenDB auto generated document identifier for the product document ends up looking something like this: products/1. (More information about the RavenDB document identifiers one of the documentation pages. ) So the URL to access that product resource for editing would really have to look like this: http://localhost/products/edit/products/1. Well that doesn’t work for two reasons:
The default route will not be matched so the URL will not be routed the correct controller action.
The URL is not SEO friendly.
Typically, this can be solved by using a custom route that access this resource by a natural key where the URL would probably end up looking like this: http://localhost/products/product-name/edit. This makes the URL SEO friendly, easy to read, and easy to route. However, there are some situations where the document identifier makes sense and I will continue this post on the assumption that this is the case.
The blog post mentioned above presents two solutions:
Solution 1 – Change the identity parts separator convention for the RavenDB document store.
Solution 2 – Modify the ASP.NET default route
Issues with Solution 1
Let’s look at the first solution. The suggestion is to change the identity separator convention from a slash (/) to a dash (-). The convention is really easy to change during the initialization of the document store object.
This makes RavenDB generate document identifiers that now look like: products-1. Now we can generate a URL that will match the default route and may look like: http://localhost/products/edit/products-1. I still find some issues this this. Namely, the URL is still not really SEO friendly and not really human readable. I don’t like the idea of exposing an identifier that was forced on me by RavenDB since it essentially has coupled my URL to the RavenDB identifier convention. It just doesn’t feel right.
Issues with Solution 2
This solution suggests the change of the default route to something like:
This will allow route to match a URL that looked like the first one: http://localhost/products/edit/products/1. I don’t like this either. While it does allow the default route to match and do its job. The URL is just ugly. It also clobbers the id making the route also match something like this: http://localhost/products/edit/products/more-junk/1. Obviously this is not SEO friendly or human readable. Again, it just doesn’t feel right.
After some digging and learning about more about the document identity field, identity type converters, custom identifiers with the document key generator convention, I realized there was a pretty simple alternative to the two options above. But to see it and to understand the simplicity, you have to look at the source of the problem.
The reason that MVC routes are choking on the preconfigured RavenDB document identity convention is because our models included a string based identity property. I realized I had done this on purpose to ease the mapping of the RavenDB document identifier and my object identifier. Take a look at my product object definition:
The shopping cart identifier is a string. Why would it be a string? It could have been an integer or a Guid or something else. It could have even been a natural key of some sort. Or even a compound key. It doesn’t have to be a string. Taking another look at the IDocumentSession interface we can see we have four load methods available.
After thinking about the difference between the method that accepts a string identifier and the one that accepts a value type identifier, I realized that all I had to do was change my identifier type from a string to a value type and I’m done. No fancy mapping or parsing the document identifier from RavenDB to the web browser and back. No changes to the default MVC route. No changes to the default identity separator convention. It just worked. My URLs are SEO friendly and more readable.
All I had to do was change the object identifier type.
That was easy.
Of course this doesn’t solve everything. What if I really do need a string based identifier? This will probably require tweaking the behavior of the RavenDB client. I also don’t have an answer for compound keys and other natural keys which may not be a value type. Some of these may require more thought from both the RavenDB side and the MVC side of my project. But that is another problem to think about some other time.
Michael Kennedy put this great little blog post together outlining 9 things we can do when starting a new ASP.NET MVC 3 project. It’s a good starting point since the MVC 3 web application template is already out of date with many things. Here is a quick run down of the things I do and don’t in comparison to his list:
Remove the MicrosoftMvc*.js AJAX and validation scripts.
Update NuGet packages… I do things a little differently here. I completely remove the EntityFramework package (I may add it or another ORM back in later, but that ends up usually in a persistence specific project and it is usually a micro ORM). I also remove jQuery Visual Studio 2010 Intellisense package since the contents are bundled with the updated the other jQuery packages anyway. I remove the jQuery UI package (and add it back when I need it). Update the remaining jQuery and Modernizr packages.
Love this tip! Who doesn’t like intellisense?
Already did this in step 2.
I’m not the sharpest tool in the shed when it comes to CSS. But this tip sounds like a good idea. Wonder if there is a NuGet package for Eric Meyer’s reset.css file?
I skip this step. In my opinion, the only models in my MVC project are view models anyway. So I leave the Models folder in my MVC project alone. If my project requires business models, they get placed in a business logic project. If I have persistence models, they get placed in my persistence project.
And yet another tip that I haven’t tried, but plan.
As a recap, tips 1, 3, and 4 make perfect sense. Tip 2 also makes sense, but I tweak it to fit my needs and I suggest you do to. I glaze over tip 5 and skip tip 7 because it was either previously addressed or doesn’t fit my needs. Tips 6, 8, and 9 sound like good ideas and I need to try them out.