XCode and iOS, Oh My!

           The best way to write an iPhone app, but...

 

 

iOS Development Tips

Other Rants and Raves

 

August 2011 - I began work on ShooFly version 2 in March. Version 1 was a simple whack-a-mole type game with only one level. It took a lot of work, but I learned a lot. Version 2 was to add levels, multiple flies, and different backgrounds. I felt I was in an intellectual straight jacket with DragonfireSDK and decide to "go native." Conceptually I thought this move to Mac Mini, XCode, Objective-C, and Cocoa Touch would be an exercise in spending money. It turned out to be one of the most difficult things I have taken on in the last several years. Five months later ShooFly version 2 was in the iTunes store and I was licking my mental wounds.

These days I feel like a fire seasoned iOS developer. I'm not an expert, but I know a thing or two. I know how to troubleshoot an "invalid summary", and that says something. This page is the story of my journey and a collection of tips that I hope help other new XCoders. I've also documented specific tips on iOS development for your enjoyment and my memory.

I should mention, this is not kids play. If you are not a C programmer already, good luck. You can figure this stuff out but I have to say that the odds are against you.

For the first three weekends I was fully consumed in the learning process. I started by watching 4 hours of Apple lectures; that helped with some of the foundation. I bought a book on iOS game development (see below) and copied the code for the first game example. It worked and I felt stoked. But then it was time to start porting my own code from Visual Studio C to XCode Objective C. At first I tried to mix C and Objective-C; in retrospect that was a mistake. I soldiered on, investigating and correcting one compile error after another. Then my code started running, but not running correctly. I'd fix one problem and six more would pop up. (One time six thousand errors showed up - no joke.) In VS I was used to making a number of changes and then recompiling - with a new environment that was a very bad idea. I should have been recompiling after every single change. I was tearing my hair out with odd syntax, obscure objects and interfaces, unfamiliar keyboard shortcuts, and a generally obtuse development environment. Plus, what the heck are all those square brackets? At one point She came in while I was staring at the wall and said, "you're not very happy right now, are you?" How true. I felt like a freshman in college taking nuclear physics as his first course. I felt like I was just barely treading water.

Mastery does not come easily, it requires hard work. And I worked hard at this. Every weekend and a few nights a week. Slowly the tide turned.

By weekend 4 I'd had a few small successes. I had the hubris to say that I knew how to sort out "invalid summary" problems. Of course the next day when one came up it took me hours to figure it out (Hint: it might just be an xcode issue and *your* code is actually fine). I could make progress and see things work, but I was still hacking at it. If you're a programmer you know what I mean. Try this, try that. When it works, go back to make it break, but you can't. So why did it work? Try this option in the IDE, then that. Oh God, how long can this last?

By weekend 8 I was feeling positively giddy. I could glide through XCode. When I wanted to add email to an app I read some iOS docs, did a Google search, add a few lines of code, and it worked! I understood the paradigm, saw the big picture, ate at the adults table. I even did a bit of XCode development to advance a project at work. Sweet.

Then it came time to release my new ShooFly version to beta testers and I once again descended into Hell. Oh my god. Certificates, signing, UDIDs, AppIds, BundleIds, XCode options, entitlement files, info.plist. Good lord. I eventually got it working but I had no idea what the secret sauce was. Each time I had to do it was a new set of migraine headaches. I predict that you too will fall into this pit of despair.

Now it's six months later. I've finished a second app. XCode and iOS are understandable. Not understood, but understandable. I do not fear new things. However, I still fear the app signing required to distribute an app. I look forward to knowing that too; it might take another six months just for that. *Sigh* (or should I say *Sign* ?)

Here are a few things I can recommend to you.

 

Getting into the Game

So you want to develop on a Mac? Here's what it took for me to get started:

That's it. Seems cheap.

Your other option is to buy a $29 OSX CD from Amazon. Create a Virtual Box environment on your Windows PC with a 60GB (at least) virtual disk. Use iBoot to start, then from there boot OSX. Apply a kernel patch from some website. Shut down Virtual Box and start up again. If you're lucky you can now install XCode. Every time you install an OSX update you'll need to reapply some kernel patch from some website and cross your fingers. I got it working, but I don't use it any more. You have to be willing to get bits under your nails to keep this working. I prefer to pay my money and spend my energy on productive coding. I recommend that you also just go buy a Mac.

Now download and install XCode. Yes, that is a four GB download. Go have a nice dinner and come back tomorrow to start working.

 

Apple 101

ShooFly v2 was my goal, a graphics oriented game. To that end I started with two very good books that I lugged around with me everywhere I went:

The first walked me through creating my first app, line by line. Their first sample app was the classic BreakOut brick game. It gave me enough to get going. I never made it past chapter 4 because I was on my way. Thanks to the authors for the head start. Unfortunately the only version of the book at the time was based on XCode 3 and I was using the new XCode 4. The code is still very useful but the IDE has changed a lot.

The second was a good reference for me to use when the question was around memory management, object allocation, etc. It is a complete language reference with chapters on control loops, etc. for those new to programming. You should buy it.

These days both books stay in my Saratoga home. Every once in a while I read some part of them again and gain some new insight as a nuance I ignored before now becomes clear to me. They are like two old friends.

Before trying to do much on your new system I highly recommend watching some lecture videos from iTunes University, available through the Apple Developer web site. They are excellent and gave me a good foundation on how it works. I spent hours watching these Apple lectures and I am normally a guy who just reads the manual cover to cover. You should watch:

I also recommend reading some of the Apple documentation. Here's a list from the iOS Developer Library on the Apple site:

 

Resources

The good news is that the Apple documentation is really pretty good. You have to get used to the terminology but after that I found a lot of good tips. For some reason I avoided the documentation for a long while, preferring to search with Google instead. Now I start with the documentation.

I've found that many of the solutions I find with Google are either too much or not enough. Either someone says, "Here's a sample program that exercises every possible complex option available" or I find "I overloaded initWithZoneCoder to solve the problem." XCode has undergone some massive changes in the last couple of years. Often the Google found examples are for an older version of XCode and don't apply directly.

A good site for noob tips: iPhoneExamples - I found a lot of good tips here. Stack Overflow is a wonderful site.

 

 

My First Image

Compared with DragonfireSDK, an XCode project has a butt load of stuff you need to do. When the app starts it goes to main.cpp which then instantiates the Application Delegate which then instantiates your Root View Controller, which is where you get to start working.

To put an image on the screen Dragonfire requires this::

int MyView = ViewAdd( "Welcome.jpg" ,0,0);

In XCode this is what I do:

NSString *myFilePath =  
        NSBundle mainBundle pathForResource:@"myfilename" ofType:@"png" inDirectory:@""];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:myFilePath]];
[self.view addSubview:myImageView];

I ask you, what could be harder than figuring *that* out? (Thanks iPhoneExamples!)

And if you want to have a touch sensitive area that covers the entire screen this is how you do it in DragonfireSDK:

Main() {
     MyTouch = TouchAdd( 0, 0, 320, 480, MyTouchEvent, 1);
}

int MyTouchEvent( int id, int event, int x, int y) {
       if ( event == 3) {
             // Do whatever you want here
       }
       return 0;
}

In XCode I have to do a lot more:      

-(void) viewDidLoad {    
    UIView *myTouch = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
    myTouch.backgroundColor = [UIColor colorWithRed:1 green:1 blue:0 alpha:1];
    myTouch.userInteractionEnabled = YES;
    myTouch.tag = 101;
    [self.view addSubview:myTouch ];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     for (UITouch *thisTouch in touches)
    {
        if (thisTouch.view.tag == 101) {
             //Do whatever you want here
        }
    }
}

You'll see some parallels between the set up for touches and images, so there is some learning you can lean on. Not everything is new every time.

 

The Good

I have to say, the XCode IDE is one slick piece of work. The intellisense typing is very good. Right click (I use a Windows mouse and keyboard) on a variable and you can jump to the header file defining it. Control click on it and you get a link to the Apple doc for the object.

Bring up a xib file for editing and you can right click on an object and drag drop to indicate a delegate, a data source, an outlet. My first app set up all the controls programmatically, the second app I used the IDE Interface Builder. Nice to know how to  do it both ways.

 

The Odd

For me, as a Microsoft Windows jockey I am constantly hitting the wrong key. Do I use Option, Control, or Alt to get something done? I finally got to where I would stop and question myself before hitting the ctrl-C key for a cut operation. Right, move over to do an alt-C instead. However, now when I go to my MSoft system I also stop to question myself on these operations - that has slowed me down a lot in the MSoft environment. Grrrr.

You are a serious developer or else you would not be contemplating a move to iOS application work. So I know you are using a source control system. I like my source control integrated with my IDE and XCode has some very sweet features. All good except for the initial set-up. I use Subversion and could not find a way to get my repository authorization credentials into XCode. A friend told me to install a command line version of any Subversion client and use its command line to connect to my repository. Apple magically stuffed those credentials somewhere. After that XCode showed little icons next to modified files. Isn't there some better way to do this?

In XCode there are some places where a couple of buttons appear together in a group. The buttons modify the views that are present in the IDE. Sometimes a view changing button bar is composed of binary buttons - click to show, click to hide. Other times a button bar is composed of view choices - click 1 or click 2 or click 3. The two look the same but behave differently. Being new to Mac I spent some time clicking on a view choice button trying to change its state. For a while I just gave up and left the "assistant" window showing because I couldn't get rid of it. Doh!

 

The Bad

The IDE has a lot of options that you have to manipulate in places you wouldn't think to look for. There was a huge change from XCode 3 to XCode 4. Many examples still reference 3, which doesn't help at all on 4. Sometimes a hint will reference the compiler hidden value of some field while the IDE shows a more user friendly name; this makes it hard to figure out how to implement the fix.

The IDE keeps evolving - at least I think that's what happens. I used to have code signing options for Development, Distribution, Release. Now I no longer see Distribution. I think I now use Release when I want a distributable package. Or have I accidentally switched some option that removed Distribution from my IDE options? This is something I'm currently researching.

The IDE provides a project file navigation view. Files in this view can be rearranged and grouped to make the view easy to use. This grouping has no effect on the underlying physical file system layout as seen in Finder. However, in your app the physical file system layout is how you reference your files. Maybe you're like me and want the project explorer to reflect the physical file system. Maybe you do a lot to keep that in sync. Then you mess up and move a few files in the project explorer. Your app keeps working. Then a month later you come back to your project and want to reference one of those files so you see it in project explorer and type in your code. Your app doesn't work and you bang your head until you realize that the file is not where you think it is within the physical file system. Doh!

 

The Ugly - Code Signing

Oh my God. What a mess. This is so frustrating. Things go wrong and you get "invalid certificate" and you have no freakin' idea what is wrong. For code signing to work it seems like 10 different settings must all agree in several different ways and Apple does nothing to help you sort it out. All you can do is change things like: Bundle Identifier, Signing Certificate, Build Scheme, Distribution Certificate, App Name, Target Name, and who knows what else. Unless this gets better you will be here a lot. I warn you, this has made grown men cry.

You should read this excellent Apple guide over and over again. You still wont understand it, but at least you'll know it's hard to deal with!

When you want to run it on a device, you need a certificate. Different articles use different terminology for the same thing and the Provisioning Portal on the Apple Developer web site sometimes uses yet another. One Apple doc on distribution even notes the problem: "issue them test provisioning profiles (also known as ad-hoc provisioning profiles)". Why didn't the Apple author need to introduce a new term "test provisioning profiles"? If some internal guru decided they would be called ad-hoc then everyone else should just stick with that. Here are some things I think I know.

You can run your app in the simulator easily. Do that until you feel good about XCode and the Cocoa Touch technology.

When you're ready, you can tether your phone to the Mac and run your application there, while still getting break points and NSLog messages in the IDE - very cool. To run on your own phone you need to have a Developer's Certificate. Go to the Apple Developer's web site, Provisioning Portal, and follow the directions to get a developers certificate. It involves the Keychain app on your Mac and is pretty easy to do. When you get the cert, download it and drag/drop it on XCode.

Next, connect your phone to your Mac and in XCode bring up the Organizer. Click on the device and click on "use this phone for development." I think that's all it takes.

When you want to give your app to a friend to try out you'll need to have an Ad-Hoc distribution profile (also known as test provisioning profiles  ;-)  ). here's what I believe to be true. All this happens on the Apple Developer web site Provisioning Center:

  1. Create a Distribution Certificate. This again requires the use of the Keychain app on your Mac.
  2. Each Apple device has a unique identifier, the UDID. You must gather these from each device you want to install your app on. With your list you can register up to 100 devices in the Provisioning Portal each year. If you later delete one of these devices it still counts towards your limit of 100.
  3. Create an AppId. Call it whatever you want, but make the name unique and meaningful for you - you'll probably want to delete it in the future once you've figured this all out and decide to redo it. Once you create it use com.yoursite.yourappname for the bundle identifier.
  4. Create a Distribution Certificate. Select Ad-Hoc. Select your App Id. Select your devices. Click Submit.
  5. Refresh the browser until your Cert is available for download. Download it and drop it on XCode.
  6. Now in the IDE the Build Setting for Code Signing / Distribution should show a choice for your cert. If this choice does not show up in the drop down, then something is wrong. What? Good luck to you.  (In my IDE it looks like "Distribution" as gone away. Does this indicate a problem with my project or do I now use the Release option? Good luck to me. UPDATE: It seems like the three choices for code signing have indeed now become only two: Debug and Release. Release is used when you want to send the app to a friend or when you want to send it to the iTunes store.)

Now you can Build for Archive.

    1. Build for Archive.
    2. If all is well an archive is created and the Organizer pops up.
    3. Tell it that you are building for iTunes distribution. Select a cert to sign the app that has the permissions you want. These are the same cert choices you had when you altered the Build Settings in the IDE. Why do we have to do it twice? Don't know. But I do know that if you pick the wrong cert here then the distribution package is crap.
    4. Choose a file name like "MyAppAdHoc".
    5. Open Finder to locate a file named MyAppAdHoc.ipa
    6. Email the .ipa file to a friend.
    7. Friend saves .ipa file to disk. Brings up iTunes. Drags .ipa file to the Library section of iTunes. Connects their device (the one you got the UDID from) and does a Sync.
    8. Viola! That's all there is to it. Simple, no? No.

Distribute your test App version via your web site.

If you take the time to set this up, then you can send a URL link to your tester friends and they can tap on the link on their device and install your app over wireless! This still only works for devices that you have registered a UUID for in your account. AND that you have selected to be active in the distribution certificate you created in the steps above. AND that you then used to sign the code when you compiled it for archive distribution in the steps above. Having done all that you now have a .ipa file you could send to them. Instead, do this:

  1. Create a directory on your web site. Say "MyAppStore.html"
  2. Copy the .ipa file up there. Let's say your file is "myApp_20111115.ipa"
  3. You need to create a .plist file for your app. I suggest myApp.plist. Click here to get a sample PLIST file you can use. Modify this file to match your app.
    • Modify the .ipa file name
    • Make sure the bundle identifier is EXACTLY the same as what you built into your app (see the -plist file in your Xcode project)
    • Make sure the release version string is EXACTLY the same...
    • I think the title can be anything
  4. Alter the MyAppStore.html to have a link in it like this
    Click to <a href="itms-services://?action=download-manifest&url=http://yourwebsite.com/myApp.plist"
    >install LottoReminderLite</a> on your device.
  5. You may need to alter your web server (certainly do with IIS) to allow .plist and .ipa files to be served up.
  6. Send the URL //yourwebsite.com/MyAppStore.html to your friends. They can open it on their device, tap the link, and viola, down comes your app.

What could go wrong?

  1. They click the link and says, "can't find file"
    - You didn't use itms-services in your href link
    - You misspelled the .plist list file in your href link
    - Your web server will not serve up .plist files - you have to configure it

  2. The app starts to download and then disappears
    - You misspelled the .ipa file name in your .plist file
    - Your web server will not serve up .ipa files - you have to configure it

  3. The app almost completes downloading and then the icon just disappears
    - The bundle identifier in your .plist file does not match the one in your .ipa file
    - The app version in the .plist file does not match the .ipa file
    - The code signing certificate you used in the compile or sign for distribution step does not include the UDID of this device

I've done this about 10 times and each time something does not work and I have to hammer at it until I figure it out. So while I'm offering you my advice above, realize that I still don't know what the hell I'm talking about. I have built my app several times for release to the iTunes app store, but I don't feel good enough about that to even offer advice...

 

Bottom Line

Dragonfire SDK with Visual Studio on a PC -or- XCode with Objective-C on a Mac ?  The choice for you depends.

If you're planning to make some balls-to-the-wall awesome app using all the current features of iOS with complexity that is going to blow the user's mind, then I think you have no choice but to buy a Mac and dive into the swimming pool. You'll learn to swim eventually.

On the other hand, if you've read my story above and are scared, then I recommend Dragonfire SDK. It has its quirks and limitations but it works.

Or, after reading this you say to yourself "Looks like a bit of work but I'm a hot shot topnotch technical person who can handle anything if I put my mind to it. *Nothing* scares me.", then what are you waiting for? Go buy a Mac and get started. And oh, by the way... that's exactly how I felt when I decided to take the plunge. You've been warned.

 

 


Jim Schrempp is a sometimes freelance writer (only Vanity Press will publish his work) living in Saratoga, California. His writings have appeared on numerous pages on his own web site. The opinions expressed in this piece are those of the writer and do not necessarily represent those of anyone else (although Jim wishes more people shared his opinions)