Fraction: Does not recognize selector forward::

If you’re crazy like me you love reading really good primers on programming. Not just to learn about a particular language but to enjoy well written technical prose. (Yeah, I said I was crazy). Yesterday, I started reading Stephen Kochan’s classic Programming in Objective-C (original edition), which was published in 2003. What I like about Kochan is how he presents the principles of object oriented programming and the syntax of Objective-C without jumping into writing a fancy application. Kochan takes his time to teach each component of the language and the paradigm instead of glossing over the details to quickly get to a utilitarian example.

If you want to understand how a great tutorial is written you can’t do much better than Kochan. Unfortunately a lot has changed in the Mac OS X world since 2003 and the code examples don’t compile. The code is fine. It’s the default compiler setting that have changed. A Google search on the compile error brought me to a a good discussion on the problem on Apple’s developer support forum. You have to dig but the fix is pretty trivial if you know gcc complier flags (which the target audience of a primer are unlikely to know).

My advice to students and armchair time travelers who want to follow the original book is to resist the urge to change the source code examples to inherit from NSObject. Instead use the -arch i386 flag as suggested by very helpful forum user Constantino. (Mysteriously Constantino’s forum name is spelled with a K.)

In other words instead of compiling with

gcc ClassName.m -o ProgramName -l objc

use

gcc -arch i386 -o ProgramName ClassName.m -lobjc

To compile and run the OOP first example of the book from the terminal you can copy and paste the following 2 lines:

gcc -arch i386 -o Fraction Fraction.m -lobjc
./Fraction

And for the full experience, don’t use Xcode or a fancy text editor. VI is fun, old school, and Apple’s Terminal a joy to work with.

Notes:

  • There is a third edition that probably addressed this issue. But what fun is that if you only have the original edition? I would love to set up an old Mac with a vintage version of the Mac OS X to really immerse  myself in the experience!
  • There is also also a Programming in Objective-C 2.0 3rd Edition which looks like a lot of fun to read and which might actually be more relevant if you have an urgent need to write a modern Mac application.

My Life in Playlists: Delran High School 1976 to 1979

me_1979

Too much has been written about High School, that American institution of adolescence, yearning, and despair. And so I’ll let the music tell most of the story. But to set the stage: I started 9th grade in the fall that followed the Bicentennial celebration of my nation’s birth; I ran with a prototype of the nerdy crowd; My girl friend was rumored to be the smartest-girl-in-school; My best friend was a body builder inspired by Pumping Iron; My other friends ran the Audio Video club as if it was the CIA; I was the worst guy on the Math Team and spent every moment I could in the Library reading Science Fiction; Worst of all I was the President of the High School Band, elected at first as a joke and re-elected because I was clearly the only soul who cared.

Point of Know Return, Kansas

But there was one thing that kept me from depression in the face of the jocks’ taunts and cheerleaders’ cold shoulders. That was Pop Music. Back then I called it Rock and it defined my social circle. While the psychological rifts between those who love Algebra and those who did not could never be crossed, every teen at Delran High School could rock out to Kansas, Thin Lizzy, ELO, Styx, and Heart.

As a freshman in High School I was only interested in big bombastic songs with lyrics that asked rhetorical questions. The fact that the word No in the title was spelled Know meant Kansas knew exactly how to get my attention. Was it a stupid pun or deep philosophical insight? I’m old enough now to know there is no difference between the two but at the time I was young enough to want to ask the question.

Telephone Line, ELO

The one High School party I remember well was at this rather popular girl’s house. None of my friends were there so I was bored and ignored. (I’m not even sure how I got invited.) To escape my anxiety I decided to man the record player and be the DJ. Nested in the middle of a stack of LPs was ELO’s A New World Record Album. Back then a big part of the experience was the artwork on the cover and ELO’s bright neon logo signaled icy crisp newness—So I plopped it on the turntable. I don’t down know what happened the rest of the night during the party but I still remember every song.

Jailbreak, Thin Lizzy

After school I hung out at a pizzeria in strip mall located at the halfway point between home and DHS (Delran High School). For the price of a coke and slice of sicilian it was my home away from home. I couldn’t afford to buy every album that interested me so the pizzeria was my focus group and cultural roundtable.

Thin Lizzy’s album Jailbreak was much discussed. The cover art looked as if Marvel Comics created it. Most of the songs seemed to be about a bunch of tough guys who called their girlfriend a “good looking female”. At the age of 15 I found this frank form of speech quite intoxicating.

Freebird, Lynyrd Skynyrd

At the time I was not a fan of Lynyrd Skynyrd and Southern Rock (I would drastically revise my opinions when I opened my ears and listened). But Freebird was the official theme song of the DHS prom in 1977. I was a sophomore and it was the only prom I attended. The smartest-girl-in-school was my date. I now realize my prom was a tame and chase affair compared to the Jersey Shore-inspired extravaganzas of the 21st century. I dined, danced, and stayed up to 3 am. Freebird did it job.

God Save the Queen, Sex Pistols

In my final year of High School (I only stayed for 3 out of 4) my musical taste was irreparably changed forever. In the middleclass bedroom community of Delran, I was securely well insulated from Punk, Europe, and Life with a capital L. (Remember, there was no Internet, that I knew of, back then—No MTV either.)

By this time the smartest-girl-in-school had graduated early and gone off to University. In my isolation the pulsing beacon of Punk rock was beginning to worm its way into my consciousness. Bombast was replaced with raw angry beats. I’m not sure where I first heard the Sex Pistols. I didn’t understand what it was but I immediately knew that I wanted to be part of it in some way, some how.

Psycho Killer, Talking Heads

This song , this album, this band was it. Unlike the Sex Pistols, which were beautiful, incomprehensible chaos, the Talking Heads were pure tension under a thin taunt layer of control. David Byrne sang songs about nothing and therefore, of course, everything.

What I liked best about the Heads was the clarity of purpose in their music: Not one note or beat was out of place. There was no fat, no frills, and no flourish. Their sonic tone of austerity only served to heighten the buried emotion of songs like Psycho Killer. It was the Heads who broke me like Tommy’s mirror. I forgot the High School band, put my sax permanently in its case, and bought a white-bodied replica of a fender Stratocaster. I believe this was the only important possession I brought to collage.

Delran High School 1976 to 1979

 

Hey It’s Easier Than You Think (Xcode 4 and Subversion)

I love how the new Xcode 4 shows you code changes side-by-side with it’s version editor view. But I had a little problem. I’m a subversion fan. Yes, I know, totally not cool. I keep this flaw a secret and I don’t force my preference on my co-workers nor do I tweet about it. I’m sure with years of therapy and the love and support of my family I’ll get over it.

But in the meantime I’m working on an iPhone game and I have a free subversion repository from my ISP. I want to continue to use this fee repository even though Apple gently nudges you to GIT with Xcode 4.

I’m stubborn. I tried GIT and it’s not doing anything for me. My change control needs are small. The functionality that makes GIT great is way more than I need: I’m not working on a large team with a complex build system that has to commit changes with the finesse of a tightrope walker.

Today I went back to subversion and my free repository when I had to update my iPhone to the release candidate 3 of the Cocos2d framework (which is host on Github BTW). Back when Xcode 4 was release I just could get Subversion and Xcode to play nice. But being stubborn, I tried again and to my surprise succeeded.

I don’t think Apple changed much. I think I was just impatient and misinformed. There is a lot of silliness about how to set up Xcode 4 to work with a Subversion repository on the Internets. What worked for me is the functionality that Xcode gives you out-of-the-box (without using the terminal). It was point-and-click but just not automated.

If you’re interested here is how you get a hosted subversion repository to work with Xcode 4. Have fun and don’t sweat the snickers from your more version control evolved friends 🙂

  1. Create a new Subversion repository that you can access via your protocol of choice (mine is the open Internet and HTTP because that’s what Dreamhost provides). Leave this repository empty–we’ll use Xcode 4 to set up all the directories. Just remember your URL and password.
  2. Open Xcode 4 and go the Repository tab in the Organizer Window.  Click the tiny little plus sign in the lower left corner to add a connection to a Repository. Enter in the URL and password and wait for the little circle to turn green. Xcode 4 should automagically detect the type of repository. Be patient. This process takes a bit of time and there is absolutely no feedback: Apple forgot to spin the beach ball here.
  3. When you get the green circle click on the root directory icon on the left under the name of the repository and create 3 directories using the New Directory button on the bottom: trunk, branches, tags. Be patient again and wait for the directories to show up in the center pane of the Organizer window.
  4. Click on the name repository on the left and enter the names of our your 3 directories in the 3 fields provided. (See the genius of naming them trunk, branches, tags?) If your spelling is good you’ll get 3 more green circles.
  5. Click on the Trunk directory on the left and then click on the Import button on the bottom. Select the folder that contains the project you want to put under source code control. Now go away. Get a drink and watch an episode of South Park. You have to be patient because not only is there no beach ball, spinner, or progress bar, there is no green circle!
  6. When you come back you should see your imported directory listed on the main pane. If you click the arrow to the left of it you’ll find your Xcode 4 project file and a subdirectory of files. Remember to be patient. Your poor overworked laptop has to ask the Subversion server for all this info and it takes way longer than 200 milliseconds to get back to you.
  7. Make sure your original Xcode project is closed and hidden away for safe keeping. Click on the imported project in the main pane of the Organizer window and click on the Checkout button on the bottom. Select a location on your hard disk to store your working copy of the project that won’t conflict with the original project. It should be OK to overwrite the original but I’m just paranoid. (Years of experience will do that to you.)
  8. Get a cup of coffee and troll Reddit for some laughs. When you come back Xcode should ask you in a dialog box if you want to open the project that you just checked out. Say yes and run it just to be sure it’s all there. (Paranoia again, sorry.)
  9. Now make a change to your and look for the little M to the right of the file name in the Project Navigator pane to show up. Be patient. If it’s not showing go back the the Organizer Window, back to your Project folder (by selecting its name on the left), and click the Commit button. The little M should now and forever show up next to your modified files in the Project Navigator.

I’m still having a little problem committing from the context menu in the Project Navigator but I can commit just fine from the Organizer Window. Maybe that’s just how Subversion works with Xcode or more maybe I have to be even more patient. I’ll let you know!

Don’t Cry For Me Ubuntu (Cry for Sata 6G)

Apparently Ubuntu is not for me 🙁

I have have this commodity PC that I snapped together to play Windows games. (Gaming is about all that Windows is good for these days.) So I though I would install Ubuntu and find some other fun things to do besides killing trolls and jumping through portals.

Every time I attempt to install Ubuntu the installer politely informs me that I do not have a hard disk attached to my PC. This is odd because I remember snapping it inside the case myself. (In fact I slid it in backwards the first time around and it got stuck and I had one of those classic /faceplam moments.)

I’ve tried both Ubuntu 10.10 and 11.4 to with no joy. I get stuck in the place inside the installer with the message:

(X) Has at least 4.4 GB available drive space

(The X above is a bad thing.)

I can run Ubuntu off the CD and Disk Utility doesn’t see the drive while GParted states tersely: No devices detected in the lower left corner of it’s status bar. The Unix command fdisk -l returns nothing.

Windows 7 has never had a problem detecting my hard disk. It’s pretty vanilla Western Digital Caviar Black with 1TB of space. It’s not some exotic brand or tech.

When I turn to Google for help I can see immediately this is not a common problem–not many search results. I found this post on the Ubuntu forums that describes a similar problem. Except that the poster has an HHD drive (which is part SSD and part normal drive). But the responses to his problem are not helpful and the thread just dies.

Western Digital’s support forum was not helpful. With the drive invisible tips for tuning it’s performance are just mean.

Currently I have 3, no 2, theories:

  1. I didn’t set a jumper properly or I somehow wired up the drive in a crazy way when I assembled the computer. That Windows 7 can work with my drive seems to disprove this theory but maybe I accidentally hit the Hide from Ubuntu DIP switch.
  2. My BIOS is not setup properly or my drive settings are screwed up. I don’t know much about BIOS but initial Google searches seem promising. I tried changing the SATA configuration settings from IDE to AHCI and from Enhanced to Compatible but without making a dent in the problem. Windows 7 boots no matter how I configure my SATA drive while Ubuntu continues to ignore the drive. This post on the ASUS Suport forum might yet bear fruit.
  3. Windows 7 has a clever hack that prevents Ubuntu’s installer from recognizing hard drives. (I’m just not this paranoid!)

I could just post on some forum but I’m kinda of bullheaded an want to figure it all out for myself. It’s hard for me to believe I have an actual new problem that the world has never seen before.

I will update this post as I progress. Comments welcome 🙂

UPDATE #1:

Theory 2 is disproved. I used ASUS Update to bring my motherboard’s bios up to date and the Ubuntu installer is still not cooperating!

UPDATE #2

Theory 1 is proven! Kinda. My WD Caviar Black drive supports SATA 3G and SATA 6G. So when I originally built my gaming machine I plugged the drive cable into the SATA 6G connector on my Asus P6x58D Premium motherboard. Windows 7 is ok with SATA 6G but I guess Ubuntu is not. SATA 6G is a new standard that is supposed be faster–but IRL isn’t much better than SATA 3G. (At least according to these guys.) When I wired up my drive to the SATA 3G connector Ubuntu recognized it!

So it’s not me that Ubuntu dislikes–it’s new fangled drive interfaces that don’t provide real value!

Cocos2d Tip#3: Making Your iPhone Game Fast

My first iPhone game, that might actually make it to the App Store, is just about done. (Not done done but almost ready for testing and tweaking.)

With the idea that other people beside me might actually play my game I’ve started to do a very dangerous and high risk activity: Optimization!

The all the famous Computer Scientists and Software Architects agree: Optimizing your program is a necessary evil, like the death penalty or bug tracking systems, and to be avoided at all costs.

Well, that’s not quite true. It’s premature optimization that is the bad guy here. Don’t start out programming with performance or scalability in mind, least you optimize code that doesn’t need it and miss optimizing code that really needs it. (It’s the same for bug tracking systems–don’t put all your junk in Jira or Bugzilla–just the verifiable, repeatable bugs that you might actually fix one day.)

When I started my game I knew my ideas were going to evolve and I didn’t want to hard code myself into a corner. I consciously wrote code that I knew would be slow but flexible.

For example I used expensive string comparisons instead of testing for cheap numeric constants. During the initial development phases of my game the strings were self-documenting (I could read them like little notes to myself) and easy to change. Later, when my game solidified and the string comparison were easy to find using Xcode’s Find in Project command (which is now Xcode 4’s Find in Workspace command)…

// before optimization
if ([goodGuy.role isEqualToString(@"tank") {
   // aggro something
} else if ([goodGuy.role isEqualToString(@"healer") {
   // fix something
}
// after optimization
switch (goodGuy.role) {
   case CharacterRole_tank:
      // aggro something
      break;
   case CharacterRole_healer:
      // fix something
      break;
   default:
      // oops! This should not happen
      CCLOG(@"unknown character role in %@",NSStringFromSelector(_cmd));
      break;
}

Changing the type of Character’s role property from NSString* to CharacterRole (a typedef’ed int) sped up my game in update methods which were called with every frame change. It was a pain to add all the constants but at least I only had to do it once–even though my conception of a Character and a role changed quite a bit.

// Character.h
typedef enum {
    CharacterRole_tank = 0,
    CharacterRole_healer = 1,
    CharacterRole_melee = 2,
    CharacterRole_ranged = 3,
    CharacterRole_boss = 4,
    CharacterRole_add1 = 5,
    CharacterRole_add2 = 6,
} CharacterRole;

// Character.m
@interface Character : NSObject  {
   NSString* _name;
   CharacterRole _role;
   // ...
}
@property (readwrite, copy, nonatomic) NSString* name;
@property (readwrite, assign, nonatomic) CharacterRole role;

Another big optimization I did was to replace for-loops and with Cocos2d’s fast enumeration macros…

// before optimization
Character* goodGuy = nil;
for (int i = 0; i < self.goodGuys.count; i++) {
   goodGuy = [self.goodGuys objectAtIndex:i];
   // do something with good guy
}

// after optimization
Character* goodGuy = nil;
CCARRAY_FOREACH(self.goodGuys, goodGuy) {
   // do something with good guy
}

My list of good guys changes during the game so I stored them in a CCArray–Cocos2d’s version of a NSMutuableArray. CCARRAY_FOREACH is a Cocos2d macro supercharged for fast array access. I could have used the Objective-C version of a fast numerator but I like to use as much of Cocos2d as I can. That way when I port my game to Cocos2d-x (C++ cross-platform version) it will be less work 🙂

One of the biggest optimizations I did was to upgrade from Cocos2d 0.99.5-rc1 to 1.0.0-rc. You have to be smart about when you upgrade to a new version of a framework. I don’t agree with the idea of living on the bleeding edge–stability of the platform allows me to focus on my own bugs!

Upgrading from Xcode 3 to Xcode 4 also seemed to help, or at least not hurt, performance. The new version of Cocos2d seems to work better with Xcode 4. I’m still getting used to the shiny new Xcode–it acts weird and slow on my Mac Mini.

To make framework and Xcode upgrades easy I put very little code into my app delegate class. All I have to do is to comment out…

//[[CCDirector sharedDirector] runWithScene: [HelloWorldLayer scene]];

and replace it with…

[[CCDirector sharedDirector] runWithScene: [HomeScreen scene]];

There are lots more optimization I can do if my performance isn’t where I want it to be: Unroll my loops and get rid of Character lists altogether. But I’ll lose a lot of abstraction and flexibility so I’m not going to optimize anything more unless my beta testers complain!

 

 

Cocos2d Tip #2: Using CCTimer in Your iPhone Game

If you’re writing almost any type of game, from a puzzler to a FPS to an RTS, tracking time is critical element of the game play. (Except for Angry Birds. You can ponder an Angry Birds level until your iPhone battery runs dry without penalty.)

Cocos2d-iPhone provides several means for tracking time in your game and scheduling methods to be called at both regular heartbeats and at arbitrary points in the future. The easiest way to manage time in a Cocos2d-based game is to use a CCLayer’s scheduleUpdate or schedule methods. Both methods are explained nicely in the timers section of the Cococ2d Best Practices guide. The guide also explains why you should try to avoid using iOS’s NSTimer class. (Your game will miss out on automatic pause and resume if do use NSTimer.)

But what if you can’t use scheduleUpdate or schedule in your game because you’re putting your game logic into a custom class instead of a CCLayer or CCSprite?

For the sake of simplicity and portability I don’t subclass CCSprite in my games. Instead, I create custom classes to represent my game objects and call update:(ccTime)delta on them from CCLayer objects to make stuff happen. I needed a nice timer class and started to write my own. About halfway though this project I ran into Cocos2d’s CCTimer. Since I’m trying to write as little code as possible I abandoned my timer. CCTimer is a nicely written, lightweight timer class that uses NSInvoker to create callbacks and still integrates will with the rest of the Cocos2d-iPhone framework.

Here’s how it use it…

First, I store a reference to a timer in my non-Cocos2d class:

// Zombie.h
#import "cocos2d.h"
@interface Zombie : NSObject {
    BOOL _resurrectable;
    ccTime _resurrectionCountdown;
    CCTimer* _resurrectionTimer; // own
    float _rebirthPenalityPercent;
}
@property (readwrite, nonatomic, assign) BOOL resurrectable;
@property (readwrite, nonatomic, assign) ccTime resurrectionCountdown;
@property (readwrite, nonatomic, retain) CCTimer* resurrectionTimer; // own
@property (readwrite, nonatomic, assign) float rebirthPenalityPercent;
- (void) startResurrectionTimer;
- (void) stopResurrectionTimer;
@end
// Zombie.m
#import Zombie.h
@implementation Zombie
@synthesize resurrectable = _resurrectable;
@synthesize resurrectionCountdown = _resurrectionCountdown;
@synthesize resurrectionTimer = _resurrectionTimer;
@synthesize rebirthPenalityPercent = _rebirthPenalityPercent;
+ (id) getInstance {
    CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    return [[[self alloc] init] autorelease];
}

- (id) init: {
    CCLOG(@"** %@: %@", NSStringFromSelector(_cmd), self);
    if ((self = [super init])) {
        self.resurrectable = YES;
        self.resurrectionCountdown = 30.0f; // half a second
        self.resurrectionTimer = nil;
        self.rebirthPenalityPercent = 0.10f; // 10% less health
    }
}
@end

Second, I define a call back method to stop the timer:

// later on in Zombie.m
- (void) stopResurrectionTimer {
    CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    if (self.resurrectionTimer != nil) {
    // the only way stop a timer is to deallocate it
        [_resurrectionTimer release];
        _resurrectionTimer = nil;
    }
    // do stuff when the zombie dies...
}

Third, I define a method to start the timer:

- (void) startResurrectionTimer {
    CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);
    if (self.resurrectionTimer != nil) {
         // if there is an old resurrectionTimer then deallocate it
         // (this is the only way to stop a timer)
        [_resurrectionTimer release];
        _resurrectionTimer = nil;
    }
    //  allocate a new timer with a built-in factory method
    // the stopResurrectionTimer method is called when
    // the time is up!
    self.resurrectionTimer = [CCTimer timerWithTarget:self 
                                             selector:@selector(stopResurrectionTimer)
                                             interval:self.resurrectionCountdown];
}

Fourth, I add a call to update the timer in my CCLayer’s update method:

// ZombieGameLayer.m
- (void) update:(ccTime)delta {
    [self.zombie.ressurrectionTimer update:delta];
}

Finally, Somewhere deep in my game logic I start the timer at the right dramatic moment.

// somewhere else in Zombie.m
- (void) die {
    // call when killed
     CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self);

    // if resurrectable start resurrectionTimer
    if (self.resurrectable) {
        [self startResurrectionTimer];
    }
}

It’s important to note that at the time of this blogging, the CCTimer documentation claims the interval value used to determine the length is in seconds, but really it’s in milliseconds (that is 1/60 of a second). If want your timer’s call back to run in 2 minutes set the CCTimer interval to 160.0f.

It’s also important to note that CCTimer is independent of frame rate: This might be obvious but sometime you want to execute an action every frame an sometime you want to execute it every few milliseconds.

If things aren’t working make sure you’ve told your layer to schedule updates in it’s init method and make sure you are updating your timers from your layer 🙂

Objective-C Memory Management For Newbies

Below you will find a list of memory management rules that will make your Coco2d game coding experience easier and your games less buggy. But before you dive in please read the caveats below:

  • These rules are based on several sources written by engineers with much more experienced than me in Objective-C and Cocos2D development. Any mistakes are my own, any good idea belong to them.
  • My sources include this tutorial by Ray Wenderlich and the comments by fufie. Ray’s tutorials should be read by every aspiring Coco2d-iPhone developer!
  • I also found this Stack Overflow question and answer on property declarations and this blog post on properties by CocoaCast really helpful as well.
  • Of course all this info is contained in Apple’s Memory Management Programming Guide in greater detail. RTFM, as they cheerfully remind us in IRC, is a great way to learn.
  • In many ways this blog post is just a briefing on all of the above material and my motivation for posting this info is just to have it all in once place and neatly summarized.
  • Finally, these rules are guidelines for inexperienced developers, not laws. Engineers who are experienced with Objective-C memory management and Cocos2d don’t need these rules and shouldn’t even bother to waste their time and read my post. Following these rules will keep newbies out of trouble with their first game or two.

10 rules that make memory management a breeze…

Rule #1: Always create properties for your ivars in your .h and synthesize them in your .m.

// in MyClass.h
@interface MyClass : NSObject {
@public NSString* _moniker;
}
@property (nonatomic, copy, readwrite) NSString* moniker;
@end

// in MyClass.m
@implementation MyClass
@synthesize moniker = _moniker;
@end

Rule #2: Use an underscore so the compiler can distinguish an ivar from a property with a common root name. When synthesizing remember to associate the ivar with the property. This way the compiler will yell at you if you try to set an ivar as if it were a property.

@synthesize moniker = _moniker; // ivar = property

Rule #3: Always access your internal properties through self using dot syntax to ensure proper memory management through property declarations.

self.moniker = @"Betty"; // the ivar _moniker now refers to a new copy of the string "Betty"

Note: In C, C++, and Objective-C the operand on the left must be an lvalue so you can’t chain assignments. Code like

self.rectangle.top = 10;

generates a compiler error.
Instead you have to unpack the object and assign it back to the property:

Rectangle* rect = self.rectangle;
rect.top = 10;
self.rectangle = rect;

Rule #4: Always provide an object factory class method to create an instance of your custom objects using autorelease for simple memory management.

+(id) getInstance {
	return [[[self alloc] init] autorelease];
}

Rule #5. When declaring a property for a basic type or for objects you don’t own use the assign attribute.

@interface MyClass : NSObject {
@public int  _counter;
@public NotYourObject* _notMyObject;
}
@property (nonatomic, assign, readwrite) int counter;
@property (nonatomic, assign, readwrite) notMyObject;
@end

Rule #6: When declaring a property for a subclass of NSObject use the retain attribute to retain the object on assignment and release the original object (if any) associated with the property.

@interface MyClass : NSObject {
@public Something*  _thing;
}
@property (nonatomic, retain, readwrite) Something*  thing;
@end

Rule #7: When declaring a property for an NSString use the copy attribute to create a copy on assignment and release the original string (if any) associated with the property. You probably want the assigned string and the original string to be two independent objects.

@interface MyClass : NSObject {
@public NSString*  _moniker;
}
@property (nonatomic, copy, readwrite) NSString* moniker;
@end

Rule #8: Use the autorelease to automatically release objects when you are done with them.

self.thing =  [[[SomeThing alloc] init] autorelease];

Rule #9: Apple API calls that begin with “init” or “copy” need to be managed by you and released when you’re done with them. You can use rule #8 to make releasing objects at the end of a method painless.

self.moniker = [NSString stringWithFormat:@"%@ number %i", @"Betty, 2]; // already autoreleased
self.moniker = [[NSString initWithFormat:@"%@ number %i", @"Betty, 3] autorelease]; // needs autorelease

Rule #10: Always use the nonatomic attribute when declaring properties unless you are working with multiple threads–and if you are working with multiple threads you are way above the level of these rules.

@property (nonatomic, assign, readwrite) int counter;

Rule #11: Always use the ivar in your delloc method to release objects you own and set them to nil (to ensure safe subclassing).

[_moniker release];
_moniker = nil;

A thought on static analysis…

Xcode’s Build and Analyze (Shift-Cmd-A) always drives me crazy with false positives. First, it finds potential issues with the Cocos2D framework source files and I’m not about to worry about or fix any of those. Second, all the issues it finds in my source files are either trivial non-issues (an assignment hidden inside an if-then-else block) or not problems at all (releasing object that it thinks I don’t own). But perhaps it’s my coding style that needs to improve. I hate letting warnings go by unresolved and as soon as figure out a way to write code the makes static analysis happy I’ll let you know.

Cocos2d Tip #1: Changing a Sprite’s Image Simply

I’m writing an iPhone game using the Cocos2d-iPhone framework. It’s been smooth sailing except for one little detail: I want a sprite to change it’s image based on a touch.

I think the problem is that there are a dozen ways to do this in Cocos2d. I wanted to find the simplest way to do it. A quick Google search pointed me in the direction of CCAnimationCache and CCTextureCache.

CCAnimationCache is used for running multi-frame animations inside a single sprite. I only have 2 frames for my sprite! CCAnimationCache could do it but it’s a more power than I need to respond to a touch. (If you want to give animation a try check out Ray Wenderlich’s wonderful tutorial.)

CCTextureCache would have been the way to go if I hadn’t already used CCSpriteFrameCache to load all my sprite images at the start of my game. CCSpriteFrameCache uses a plist that divides up a large image into rectangle so you can pack all your sprite images into one memory saving “texture atlas.” And you can use Zwoptex to generate the image and the plist for you. CCTextureCache is the manual way to do what CCSpriteFrameCache and Zwoptex automates for you. (If you like to be hard core check out Ben’s post on optimizing texture loading.)

I figured there had to be a way to use my sprite frames in my existing cache without having to resort to manually loading textures or creating animations I didn’t need.

There was! It’s simple and here’s how to do it…

First, create your texture atlas with Zwoptex and add the .plist and .png files to your Resources folder in your Xcode project.

Second, load the texture atlas into the shared frame cache early in your game…

CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
[frameCache addSpriteFramesWithFile:@"textureAtlas.png"];

Third, create your sprite in your layer’s – init method…

// Note: niceSprite is a CSprint* instance variable so we can reuse it
niceSprite = [CCSprite spriteWithSpriteFrameName:@"initial_image.png"];
niceSprite.position = CGPointMake(240, 160);
[self addChild:niceSprite z:0 tag:0];

Fourth, in your – ccTouchBegan or – ccTouchesBegan method add the following code to change the image associated with your sprite…

CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCSpriteFrame* frame = [frameCache spriteFrameByName:@"new_image.png"];
[niceSprite setDisplayFrame:frame];

That was easy!

I Bought A New MacBook Pro and Didn’t Pay an Arm and Leg!

Apple had a sale over the Thanksgiving weekend. The savings we’re exactly in Crazy Edie territory but $101 off a new MacBook Pro just about covers the tax (in NJ). My last MBP has been sitting in pieces on the bookshelf behind my desk at home. I bought it in 2008 and two years of daily commuting between NJ and NYC literally shook it apart. I used Apple’s sale as the thin, poorly veiled, excuse to buy a new MBP. The truth is I’m just addicted to shiny new computers and I had to feed the monster.

When it comes to buying a computer I have three criteria:

  1. Don’t buy something that will become obsolete in a quarter.
  2. Don’t buy less or more power than I need.
  3. Pay as little as possible while still buying something that won’t embarrass me in front on the cool kids.

When I met my wife she explained to me that you can tell a lot about a person by their shoes. A cool hip guy might walk around in an outfit from Target but the brand of his shoes will tell you if he is being ironic or a showoff or a cheapskate. In the 21st century you can apply the same criteria to computer laptops. Some guys (or gals) buy the most expensive luxury desktop replacement money can buy as if to say: “I’m bad!” Other guys buy the cheapest under powered plastic toy “puter” that buy.com has on sale as to say: “I make Scrooge McDuck look like Bill Gates! (The current Bill Gates not the earlier one who acted a lot like Scrooge McDuck before he got married.) Then there are understated nerds like me who try to say something nuanced with their laptops: “Yes it’s not the fastest, but we know that RAM and HD speed are more important than raw CPU speed for real world applications.”

After much research and discussion with my hardware otakus this is what I bought and why:

I bought a 15″ MacBook Pro with a 2.40 GHz Intel i5 core CPU with 320 GB hard disk and 4 GB of RAM. This is the least expensive 15″ model Apple sells at $1799. I asked Apple for one extra: A higher resolution LCD display (1680 x 1050 instead of 1440 x 900) at only $100 more. With the Apple sale I got the hires screen for free but at only $100 for 30% more pixels it’s a bargain–one of the few true steals to be found in the Apple Store.

The display resolution is why I bought the 15″ and not the 13″. More pixels means less scrolling and more productivity. But I could have bought the 17″ MBP with a whopping 1920 x 1200 screen resolution. But I’ve used the 17″ model before and it’s not really portable. As a hard core northeastern corridor commuter I need something that fits into a standard backpack, weighs less then a 3KG medicine ball, and actually fits on my lap in the crowded train car.

Apple has options for much more powerful (i7 core) and faster (2.8 GHz) CPUs. But while benchmark software will show you a 25% to 30% performance boost between the 2.40 GHz i5 and the 2.80 GHz i7 pure CPU speed isn’t the problem unless you’ve unclogged all the other performance bottlenecks in your laptop.

The the real roadblocks to a laptop snappiness are memory and storage speed and size. Modern operating systems accommodate today’s bloated software applications by organizing memory usage into “pages” and swapping these pages in and out of disk as needed. Adobe Photoshop is the exemplar: It can’t let you edit that 21.1 megapixel image without shuffling pages of memory around. Some operations, like filters, are CPU intensive, but most operations (reading, writing, zooming, scrolling, copying, pasting, …) are memory bound.

To lessen the bound of memory I ordered a 4 GB ram stick and a 7200 RPM 500 GB hard disk from a third party: Not Apple! Apple charges extraordinarily high prices for RAM and hard disk upgrades. To buff up my MBP would have cost an additional $550. The third party RAM and HD only cost me $154.31 and 1/2 hour to unscrew the back of the MBP and install everything. In the end I had a sweet new MBP with 6 GB of RAM and 1/2 a terabyte of storage. Photoshop is happy.

There is a risk that by upgrading you’re Mac you’ll ruin it and void the warrantee to boot. I alway get help from my hardware friends who show me how. There are also some good videos from MacSales that we’re really helpful. The voiding of the warrantee went from a definite yes to a maybe in the last few years. Apple reserves the right to blame your MacBook problems on you if you don’t use an authorized service provider.

For me, it was worth the Geek Cred to personally upgrade my MBP so I could have a great ice breaker at Starbucks:

“Oh, this that new MBP you got there?”

“Yes, but I haved $400 bucks by upgrading it myself and I got the hires screen for free on Black Friday.”

“OMG! 2G2BT! CSA!”

The Three Laws of Agile Process

As early as 2007 Agile practitioners, or at least people who blog about Agile, began to observe that we live in a post-agile world. I’m not sure what means but Agile is a conversation about the best way to manage the software development process that has been going on for a long time. Has it been too long? What comes after Agile?

Eventually all wisdom becomes dogma.  Many engineers feel strongly that we’re already there with the process for process’ sake when the scrum master moves into the cubicle next door. Fair or unfair it’s a criticism needs to be explored. However nobody has put forth a process to succeed Agile–one that builds upon it’s strengths and shores up it’s weaknesses. At this point in the history of software development were we to abandon Agile we might as well go to ouija boards and seances to plan our projects.

So in truth, we make it up as we go along. That’s what most experienced scrum masters mean when they say they are flexible about adapting the processes of Agile to the culture and business needs of an organization. Poor Agile implementations are only a few second-guesses away from good ones.

Perhaps it’s time to take what we’ve learned in the 10 years since the framers of the Agile Manifesto met in Snowbird and create something that fits even better with the technological and business climate of the Mobile-Cloud-Long Tail-Social-Search Driven-Virtual world we log into every morning.

I’d like to start with the very first value of the Agile Manifesto:

Individuals and interactions over processes and tools

Do we still value people over process? Is it that simple? From this value the principles of customer satisfaction, working with business people, building projects around motivated individuals, face-to-face conversation, sustainable development, and team reflection are derived. Change this value and we change the equation for all of Agile. Do we weaken it? strengthen it? or replace it with something else?

Even with the unique challenges of developing software for servers you can’t touch and cell phones with fingerprints all over them we know what true process-for-process’ sake is like. We call that Waterfall but it was many more manifestations. It’s the paperwork you fill out in the emergency room and the electronic EULA you click “agree to” without ever reading.

So we have to keep it. In fact I would argue we have to make it much more imperative: A rule that is never broken which says it’s OK to break the rules!

I don’t mean we should give up our process at the drop of a hat (or the crash of a market). But we must give it up when our people will be rendered ineffectual. Issac Asimov’s Three Laws of Robotics can inspire us with a new rendering of what is, perhaps, the most important value of Agile:

  1. A process may not injure a team or, through inaction, allow a team to come to harm.
  2. A process must obey any orders given to it by a team, except where such orders would conflict with the First Law.
  3. A process must protect its own existence as long as such protection does not conflict with the First or Second Law.

If it will keep our robot overlords from killing us it will work for keeping an overzealous Agile process in check!