Wednesday, July 27, 2011

Road to devLink: Services & App Store

I am writing this post after pushing the following commits:


iOS App: 1cb26d2

Server: e2d8d02


In this commit, I have set up the first redimentary calls from the iOS app to my web service. The web service is written in node.js with a couchdb backend. I think I am going to make this one short, as the content here is more stuff that I am learning that it is stuff that I plan to cover at devLink.


iOS App

I added a lot of code I have been building up over time. I added some categories that I find helpful. I also added some stuff to manage asynchronous NSURLConnection calls. I parse the json to NSDictionarys and NSArrays using this code by Stig Brautaset.


I wrote some unit tests to validate the communication between the iOS app and the service. I was able to sort-of sleep the main thread for the tests for an arbitrary amount of time while it waits for the web call to return. It works, but it feels klunky. At any rate, these are probably more integration tests than real unit tests. Whatevs, I am not too concerned. It gets the job done.


Services

I created a README.md file, you can see that in the github branch here. That has links to the things you will need to install (node.js, npm, and couchbase). It also has some example documents that refer to the Candy Store products for sale from the App Store.


In-App Purchase Items

In iTunes Connect, I created the IAP items that will be used by Candy Store. Though it was a rather tedious effort of entering data in web forms, it was not very difficult. The best resource to guide you through the process is the iTunes Connect Developer Guide. There is also an excellent video from this year’s WWDC on In-App Purchases. Pretty much, these two things are helping me fumble through my app. Both of these resources require you to be registered in the Apple Developer Program.

Tuesday, July 26, 2011

Road to devLink: View Controllers, Web View, Services, and Tests

I am writing this post after pushing the following commits:


iOS App: a862663

Server: N/A


Open Terminal, navigate to a nice place where you would like to store this code, and then perform the following to view this commit

git clone git@github.com:danielnorton/CandyStore-app.git --branch development
cd CandyStore-app/
git checkout a862663

In this commit, I have set up the main view controllers of the iOS app, I have also set up the first vestiges of a few of the services that the app will use, and I have written a few unit tests.


View Controllers

You will see that in MainWindow.xib I have set up a UITabBarController with three tabs. Each tab holds a UINavigationController that then each hold one of the three root view controllers that represent the three distinct sections of the app (My Candy Jar, Candy Shop, and Candy Exchange).


In my devLink session, I will probably discuss this approach. I have the idea in my head that I will have this completed app and then do separate branches or something like that to implement discrete portions of the app that are pertinent to the topic at hand. So, when I am talking about view controllers, I will (in advance) create a branch of the completed app that does not have this initial setup built. Then we can step through creating tab view controllers and navigation controllers, etc. We can see how to wire them up in Interface Builder and talk about how every thing that is done in Interface Builder can be done in code.


Services

As discussed above, there are three tabs. If a user is not currently subscribed to the Candy Exchange and they tap on the Exchange tab, I would like for the app to alert them to visit the Candy Shop and subscribe to the exchange. To facilitate this, I have registered the app delegate as a UITabBarControllerDelegate. That will notify me when the tab is tapped. All of the logic to test the current state of the user’s subscription and decide if the app should notify is contained in a service. At the moment, there isn’t much logic in the service. It will probably get more fleshed out as I add a model and wire up to In-App Purchasing and my own web services. But for now, I can still build the concept that some amount of work needs to be done, and that work needs to be contained in a service. When the complexity comes later, I can change the service without having to do much work (if any) outside of it.


When the service communicates back to the app delegate, the app delegate will display a UIAlertView. When all you need is a to display a modal message to the user, it gets somewhat tedious to fill in the big init method on UIAlertView. For situations like this, I am a big fan of categories. I have created a category for this situation called UIViewController+popup. I will use this at devLink as an example of categories and how to use them.


... hmm ... I have used UIViewController+popup in a number of projects. It’s one of my little “toolbelt items”. While writing this post, the thought occurred to me that tying the popup method to a UIViewController is not necessary ... I will leave it there for now. Maybe somebody at devLink will catch it and start a good discussion.


Tests

I am a big fan of TDD, but to be honest, I am not rigorous about using it. Additionally, I don’t find the testing tools built in to Xcode to be very good. The mocking tools I see out there aren’t terribly impressive to me, and I have yet to find an IoC container / framework. So, I really don’t write a lot of iOS unit tests. But since part of this project is for my own education, I am going to make a new concerted effort. Since the services I am writing at the moment are still self contained this is working out pretty well. Here is an example of a test and, as tests go, an example of how to use one of my services (with a huge name that I don’t like typing over and over).

- (void)testShouldNotAlertUserPurchaseExchange_IncrementThree {

ExchangeSubscriptionNotificationService *service = [[ExchangeSubscriptionNotificationService alloc] init];

[service reset];
service.counter++;
service.counter++;
BOOL shouldNotify = service.shouldNotify;
[service release];

STAssertFalse(shouldNotify, @"should not notify.");
}

When I get a little meatier code, I intend on writing a post about my preferred coding style and how I like to structure the contents of the .m and .h files. service.counter++; violates my preferred style, but it works in this instance so I am not going to get all excited. My preferred style would end up as something like: [server setCounter:service.counter + 1]; which is kind of ugly in this particular scenario.


Web View

If a user has not yet purchased any candy, instead of showing an empty list for the Candy Jar view controller (the first tab), I would like to show a welcome view. I thought it might be helpful to demonstrate the use of a UIWebView in showing this welcome message. I wanted to build a single ... welcome.html ... file to embed in the app. I fumbled along with Safari Mobile CSS stuff and decided to punt and see if I could get some cheats from Dashcode. It turns out I was able to put together a rudimentary welcome view very easily in Dashcode. It only took a few minutes. I kind of liked it. It is not fancy, and it really doesn’t end up looking as whiz-bang as I wanted. I really wanted to build a thing that used multiple colors on a single line of text or something like that which would be difficult with UILabel. But, anyway, it will work for now. I will show that off at devLink. The web view is in My Candy Jar view controller. It includes a good opportunity to demonstrate a simple animated fade in for the web view when it completes loading its content. Also, this view controller will offer a good talking point of how and when to use a UITableViewController and when to use a regular UIViewController that implements UITableViewDelegate and UITableViewDataSource. For this controller, I chose the latter. This will also make a good talking point when introducing protocols and delegation in my devLink talks.


Monday, July 25, 2011

Road to devLink: Intro: Candy Store demo app

Update: Here's a list of the following relevant blog posts

  1. Intro: Candy Store demo app
  2. View Controllers, Web View, Services, and Tests
  3. Services & App Store

I have a number of technologies that I am dinking around with at the moment. I also need to prepare some demo code for some upcoming talks at devLink. I would like to try building all of this together. I would also like to do it completely in the open, so that you can watch my progress. This might be a good way to sneak in some posts that I have been meaning to create for some time like coding style and memory management considerations with properties.


I have a general idea of what I want to build. I have a few drawings. I have no idea how this is going to work out. Perhaps I will fly right through the project, learn some great things, give a great talk at devLink, and the end result will prove this initial post to be a prophesy of success. Perhaps I will get a few posts into it and the entire thing will crash and burn. I’ll still give at least a good talk at devLink. Perhaps this experiment will land somewhere in the middle.


Let’s start with a description of the problem that I would like to solve and how that is going to drive my first few decisions. The problem I would like to solve is to build an educationally productive demo app that makes cohesive use of several key technologies. The technologies I would like to incorporate are as follows.


For my own learning:

For my devLink talks:

It is important to keep in mind that my primary goal is to build an app that is an educational aide; both to me and to my “students” at devLink. Therefore, I am very comfortable with a contrived business problem. In fact, I am really fine with that. There are always limitations on using “real world” code from a real client. Instead, since there is no actual business problem, I am free to invent some nonsense and build for it. However, I want to build something that is a bit more polished than a typical demo app. It would be great if, at the end of this, I were able to say the app is more-or-less production ready except for the one caveat that the business problem that is solved is complete bullocks and no one would ever, ever, ever buy this ridiculous app.


So, here goes. My project is called Candy Store. The basic idea is an app where a user can buy, “eat” and trade virtual candy. Here is a first drawing of the basic idea of the app.


As you can see, there are maybe ten or so views. The primary view controller will be a UITabBarController. It will host several customized UIViewControllers, possibly with some UIWebViews, a few UITableViewControllers, and of course some UINavigationControllers.


The local data will be stored in CoreData. The app will call out to my web services and use StoreKit for the IAP stuff. The web services will be written in node.js with a couchdb backend.


So, where do you keep up with my progress? Well, firstly here on this blog. I will amend this post to include links to additional relevant posts. I will be using github for source control. You can find the app and server repositories here:


https://github.com/danielnorton/CandyStore-app

https://github.com/danielnorton/candystore-server


At the time of this writing (July 22, 2011) there is little more in each repository than the initial project setup.


More coming soon.

Friday, July 22, 2011

Notes from Debugging live apps in the App Store

I recently released an app to the App Store. We are getting reports back from users that the app crashes on certain versions of iOS. Following are the steps I took to figure out the cause of the crash.
  • Firstly, I logged in to iTunes Connect
  • clicked "Manage Your Applications" -> MyApp -> View Details -> Crash Reports
  • downloaded the crash report to my local machine and unzipped it
  • opened Xcode -> Organizer -> Archives
  • selected the build that I had submitted to the App Store, control-clicked it, chose Show in Finder
  • control-clicked the .xcarchive file and chose "Show Package Contents"
  • copied the files /dSYMs/myapp.app.dSYM and /Products/Applications/myapp
  • pasted these files in the same directory as the unzipped crash reports. The contents of that folder looked something like this:
MyApp_1-1_2011-07-22_iOS-5-0_Top-Crash_1_1.crash
MyApp_1-1_2011-07-22_iOS-5-0_Top-Crash_1_2.crash
MyApp_1-1_2011-07-22_iOS-5-0_Top-Crash_1_3.crash
myapp.app
myapp.app.dSYM
  • I opened the first crash report, MyApp_1-1_2011-07-22_iOS-5-0_Top-Crash_1_1.crash, in a text editor. Here's what the first little bit looked like:
Date/Time:       2011-07-19 14:44:19.660 -0700
OS Version: iPhone OS X.X (XXXXXXX)
Report Version: 104

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0xa0020008
Crashed Thread: 0

Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3490807c objc_msgSend + 20
1 Foundation 0x31f2e2a4 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
2 UIKit 0x359071bc -[NSIndexPath(UITableView) row]
3 myapp 0x0000a728 0x0000a728
4 myapp 0x0000a074 0x0000a074
...

Thread 0 is the thread that crashed. Below the statement "Thread 0 Crashed:" you can see the first few lines of the offending backtrace log. Each line is the next level up in the backtrace, also called a stack frame. Stack frame 0 is the message that crashed, it was called by stack frame 1 which was called by stack frame 2, etc.

The first thing I looked for is _my_ code that was nearest the top of the call stack. In this instance, it was stack frame 3. Next to the name of my binary (myapp) are two similar hex numbers. These numbers correspond to the address of the command that is being called in that stack frame. Since frames 0 - 2 are Apple code, I can see the names of the messages. However, the crash was generated from ... somebody's ... iPhone. Since that person does not have my app's debugging symbols loaded on their phone (no one ever would) the crash report only shows the address of the message, not the name. So, my task is to figure out the line of my code that corresponds to address from the crash report. The command line tool 'atos' will help in this instance.
  • copied the address of stack frame 3
  • opened terminal, navigated to the directory
  • issued the following command
atos -o myapp.app/myapp -arch armv7 0x0000a728

This showed me my offending line:
-[MyClass myMessageThatDoesStuff:] (in myapp) (MyClass.m:327)

OK! I could see that the offending line was the message myMessageThatDoesStuff: in MyClass at line 327. I opened my code and had a look
I needed to see what message called myMessageThatDoesStuff:, so I copied the address from stack frame 4 and ran atos again.
atos -o myapp.app/myapp -arch armv7 0x0000a074
with the response of something like:
-[MyOtherClass myOtherMessage:didDoStuff:forUser:] (in myapp) (MyOtherClass.m:231)
So, I inspected MyOtherClass at line 231.

Eventually, this technique helped me to find my code that had released an object and then turned around and tried to use it. derp.