• Objective-C/Cocoa Tips

    [Updated 7 November 2010.]

    I've been writing Objective-C and Cocoa code for almost 8 years, but it feels like a lot longer. There is good reason for that and it's that during that time I haven't just worked on projects during the day, I worked on projects at night, so the 8 years is more like 10-12 years of writing code. During that time, I've written a ton of code and come up with a lot of tips to help me. Each developer has his/her own style, so I'm sure that some people will take objection to some of what I say. However, a number of projects I've worked on could really have used this information to be more solid.

    Without further ado:

    1. When you start a project, set the Organization in the project so that all new files created have the correct copyright. Pretty much every project I've worked on has most of the files stamped with the wrong copyright.
    2. Never use [self autorelease] or [self release]. These make code very hard to trace and WILL lead to a crash when another developer comes along and releases an object thinking there is a memory leak. Code should be restructured so that whoever instantiated the object releases it. In addition, CLANG will flag objects that aren't released as a potential memory leak and having to sift through the CLANG messages every time analyze is done.
    3. Follow Apple's guidelines on method naming. Methods that return an object that must be released by the caller must begin with "alloc" or "new" or contain "copy" in it. (create also seems to be in there as well). Methods that return an autoreleased object must NOT start with "alloc" or "new" or contain "copy" in it. These are important so that CLANG can analyze your code and not flag things that require you to have to go through each issue and trace the code.
    4. Never subclass core objects such as NSString, NSArray, NSSet, etc. If you need additional functionality either use a category or make a new class that has the object as part of it.
    5. If an object is added to an array, an NSOperationQueue, etc., make sure the object is released or autoreleased.
    6. Don't use [NSObject new]; use [[NSObject alloc] init]; This is simply for readability. While they are equivalent, every time I see an alloc/init, I know I have to do a release or autorelease. "new" isn't as widely used and someone could accidentally do self.object = [NSObject new] which would cause a memory leak if the object property is retained.
    7. Use assign properties for objects in limited cases such as XMLNodes or delegates. In most cases properties should be retained or copied.
    8. Don't do a lot in the init methods. Also, be careful of using self.xxxx in an init method as there can be side effects in the assignment if you are using KVO or have your own setter. (The side effects part comes right from a WWDC presentation.)
    9. For properties that are retained, don't do self.xxx = [[NSObject alloc] init]. This is a memory leak. You can add autorelease to the end or do the assignment in a few steps, i.e.
      	NSObject *obj = [[NSObject alloc ] init];
      	self.xxx = obj;
      	[obj release];

      If you don't want KVO, you can eliminate using self. However, make sure you release the object before assigning it.

    10. Only use threading if you absolutely must and use NSOperations as much as possible. Threading is tricky and I've only seen a few places where it has been done right.
    11. Never make different build products using scripts, define values, and configurations. Use build targets. If you don't, your project file will change all the time and people will keep checking in a slightly modified project file.
    12. Don't put unnecessary things in the .pch file, create a Defines.h for that. Use the .pch file for including other files, one of which can be Defines.h. Put the Defines.h at the top of the project to make it easier accessible.
    13. Don't name every file in the project with the same prefix. If you are sharing code with other projects, then making those have the same prefix, that is fine, but if you have 100 files that start with SG, it becomes quite annoying.
    14. Don't sprinkle UNIX like code everywhere and don't use UNIX calls when Cocoa calls are available.
    15. If you use CoreData, first read as much as you can about CoreData. Second, explicitly set the managedObjectModel and don't let the OS do it for you. The OS will merge all the managed object models in your bundle and create 1 model. This is problematic when you have to do migrations.
    16. If using CoreData, use the XML data store until you are comfortable with the data model. Verify the metadata in the XML before you switch to sqlite.
    17. Networking code is hard. Make sure you don't use synchronous calls even in threads as you can't handle cancels. Use NSOperations for the calls. Debugging the code is even harder than writing, so don't over complicate it.
    18. Don't do version numbering in Info.plist files as you have to update 3-5 items each time you change the version number. See my post on an easy way to do this.
    19. Don't use NSAssert everywhere. Do actual error checking and handle conditions where necessary. While NSAsserts are usually compiled out for release builds, NSAsserts just annoy me to no end and basically serve no purpose to me.
    20. Make sure builds compile with no warnings. Don't ship code with build warnings unless there is some type of compiler issue preventing this from happening.
    21. Don't turn on unnecessary flags in Xcode; making warnings into errors makes it hard to test code. If you abide by the item above, you don't need to make warnings into errors.
    22. Before checking in files, always do a diff from your changes to what's in source control. Don't check in files just because you change 4 spaces into a tab. This also helps review the code and make sure you didn't leave in test code.
    23. Never store a value using NSNotFound. Seems pretty obvious to me. Apple says:

      Prior to Mac OS X v10.5, NSNotFound was defined as 0x7fffffff. For 32-bit systems, this was effectively the same as NSIntegerMax. To support 64-bit environments, NSNotFound is now formally defined as NSIntegerMax. This means, however, that the value is different in 32-bit and 64-bit environments. You should therefore not save the value directly in files or archives.

    24. Never release an NSOperationQueue from within an NSOperation. That's like pulling the rug out from under you while you're standing on it!
    25. Be careful with type casting.
      NSUInteger value = (NSUInteger) -1;

      could have very strange consequences. Likewise, doing:

      NSUInteger value = (NSUInteger) NSNotFound;

      May not do what you want it to do and the results could be different on 32 and 64 bit machines.

    These are just some tips that I've learned/developed over the years. I write a lot of code and have been involved in a number of projects that need TLC. Feel free to comment if you have more tips or want to debate anything I have written; these aren't the be all, end all to writing code, but they do help me write code that will stand the test of time (I recently got involved in a project that has code I wrote over 6 years ago that is still in use!)

     

  • How to make an outdoor fountain

    For years, my wife has wanted a fountain outside as she likes the sound of the water falling. I've bought her table top ones and even a cheap plastic one we had in our living room. The biggest problem was the pump was a bit loud and the water sound didn't cover it. This weekend, my wife decided that she wanted an outdoor fountain. This became our (my) weekend project. In this post, I'll outline the procedure I used to make the fountain. I, of course, take no responsibility for your significant other bugging you to make a fountain or for any injuries (mental or physical) sustained by undertaking this project.

    fountain.jpg

     

    Materials needed

    • Terra cotta pots
    • Glazed bowls
    • Pond/fountain pump (300 GPH or higher depending on height of the fountain)
    • GFCI outlet
    • Weatherproof outdoor outlet cover
    • Fountain nozzle kit
    • Hose from pump to nozzle
    • Plumbers putty
    • Round file

    Tools needed

    • Screwdriver (needed for GFCI installation)
    • Needle nose pliers (needed for GFCI installation)
    • Level that is long enough to span your largest bowl
    • Dremel
    • Dremel Grinding Stone
    • Patience

    Procedure

    1. Ensure that you really want to undertake this. Spending $200 on a decent fountain may be worth your time and money. Building your own takes time and isn't necessarily cheap.
    2. Make sure that Home Depot (or other home improvement store) is less than 20 minutes away. If not, stop here as you will need to make repeated trips. It only took me 5 trips.
    3. Have significant other do the research and figure out what he/she wants.
    4. Allocate a full weekend for this project. A three day weekend is best as those trips back and forth to Home Depot take a lot of time.
    5. Make sure that there is a GFCI protected outlet near where you want the fountain to go. If not, install outlet. (This was actually my last step as I realized that the outlet wasn't GFCI protected.)
    6. Install weatherproof outdoor outlet cover. This should be pretty easy, but for me, I had to cut out some siding to make it fit.
    7. Buy terra cotta pots and bowls. See picture to the right for what we chose. It took a significant amount of time for my wife to decide on what she wanted. Originally she wanted a resin whiskey barrel as the base and then didn't know what she wanted and then we went to the Canyon Pottery which has a huge selection of pots and bowls.
    8. Determine where the fountain will be. You don't want to move it after you start.
    9. Place largest terra cotta pot on the bottom upside down. Level it (very important).
    10. Plug hole in largest bowl. Use plumbers putty and whatever other means necessary.
    11. Place largest bowl on top and level it.
    12. Use Dremel to carve a notch in the second largest terra cotta pot so that the pump cord can go through it. Also, use the Dremel to put maybe 8-12 holes in the top rim of the pot. These holes let water get to the pump. The pump MUST be completely submersed in water in order to function.
    13. Attach short piece of hose from pump to an extension pipe  that comes with the nozzle kit.
    14. Place pump in largest bowl.
    15. Place second largest terra cotta pot in the largest bowl and feed the extension pipe up through the hole in the pot.
    16. Level terra cotta pot. Note that if you can't level it, you may have to use the Dremel to grind down one edge of the pot.
    17. Place second largest bowl on top and thread the pipe through. You may have to use the round file to make the hole a little larger to make the pipe fit.
    18. Use plumbers putty to seal around the pipe that comes up through the bowl.
    19. Attach second piece of pipe that comes with nozzle kit to the pipe that is coming up.
    20. Level bowl.
    21. Place third largest terra cotta upside down in bowl and make sure the pipe comes up through it.
    22. Level pot.
    23. Place top bowl on the pot and thread the pipe through it. You may have to use the round file to make it fit.
    24. Level bowl.
    25. Use plumbers putty to seal around the pipe.
    26. Put the nozzle on top of the pipe.
    27. Fill all the bowls with water.
    28. Cross your finders.
    29. Plug in the fountain.
    30. Enjoy!

     

  • Review: Blade mCX2

    After getting a Syma S107 RC helicopter, I was quickly hooked on RC helicopters. I went to the local hobby shop, Discount Hobby Warehouse, and took a look at the Blade mCX2. When I mentioned to the guy at the shop that I had a cheap $30 helicopter, he said that the goal of the cheap ones is to not crash while the goal of the more expensive ones is to fly. I definitely could agree to the part about not crashing. I bought it and when I got home, I charged the battery and was off and running. I was easily able to fly it around for a few minutes until the battery died (I get about 6 - 6 1/2 minutes per charge). I've picked up a few more batteries and have been spending at least 20-30 minutes a day. I'm definitely a fan.

    Everything I've been reading indicates that the coaxial helicopters (CX) are easy to fly and are beginner helicopters, so I think I picked the right one. The mCX2 is easy to fly inside (it is far too small to fly outside as the wind will knock it around). The entry price is reasonable (for a hobby), but the cost will quickly add up, so be prepared. I've already bought a few more batteries, a four port charger with AC adapter, and due to a crash, some spare parts.

    Speaking of crashes, while the helicopter is easy to handle, if you want to start to get fancy, it's quite maneuverable, so much so that it isn't that hard to crash. I made the helicopter yaw a bit too much and then over corrected which lead to the crash. The crash cost me about $15 in parts to repair. Even though the parts are quite small, repairing it, isn't that hard. It comes with a small phillips screwdriver and combined with a pair of locking forceps  that I got at an Army/Navy Surplus store, repairs just take a little time and not much skill.

    The mCX2 uses parts that are shared with other helicopters made by Blade, such as the mSR and mCX Tandem Rescue, so if you get one and want to upgrade, you already have some pieces.

    Pros

    • Compact size allows you to fly in the house.
    • Easy to control.
    • Captivating (I'm really hooked).
    • Challenging. While easy to control, I'm teaching myself how to land it in a small area which is proving to be easier said than done.
    • Easy to repair.
    • Individual parts aren't that expensive.
    • Relatively durable. It handles small crashes well.

    Cons

    • Price. Some may say that the price is a little high. I think the entry price isn't bad, but it starts adding up quickly.
    • Only comes with 1 battery.
    • Short flight time. Due to the small size of the helicopter, it has to have a small battery, so this is understandable.
    • Only comes with a 1 port charger. Charging 1 battery at a time means you have to wait 30-40 minutes for it to charge between flights.
    • Charger runs on 4 AA batteries; AC adapter is optional. The manual says that the AA batteries will charge the battery 15-20 times. Since I started with 2 batteries, and I flew it as often as possible in the first few days, that the batteries only lasted 3-4 days. This cost savings is not very green and is extremely annoying. I went ahead and got a 4 port charger with an AC adapter and now I can run through 4 batteries and then charge them all up.
    • It's addictive.

    Summary

    For some reason, I've always been fascinated with things that fly. So, when I tried my first helicopter a few weeks ago, I quickly realized that I may have found a hobby (up until now, I really haven't had a hobby as an adult). The mCX2 is a great entry level helicopter and provides hours of fun. If you think that the cost of the helicopter is the end of spending money on it, I wouldn't get it. The costs will start adding up quite quickly. I mentioned this helicopter to a friend (he already had a few other helicopters) and he bought it based on me talking about it. He seems quite pleased with it as well (his dogs aren't pleased with it, however).

    This helicopter is not a toy, so heed the age level on the box (14 and up). I'm not sure it is appropriate for a 14 year old, however.

    I'm very happy with my purchase and can definitely recommend it to anyone that has ever been interested in RC helicopters.

  • Review: ezDesktop - VNC client for iPad/iPhone

    I've been using a Mac Mini as my DVR/media center for about a year now and there are times when I have to pull out my laptop to control it despite having a Harmony Remote configured for it. If we want to watch shows on USA Networks, TNT, etc. in a web browser, I can't control that with a remote (at least not until Google TV or the like comes out).

    The other day I really didn't want to use my laptop to control the Mac Mini, so I looked at VNC clients for the iPad. I found 2 that had free (trial) versions. Mocha VNC and ezDesktop. Mocha VNC Lite didn't impress me. I turned on the VNC server on my Mac Mini, setup a password, and easily connected to it with ezDesktop. I played around with it, managed to navigate fairly easily with the iPad and did some web browsing. By the time I had done all this, my free session was up and I decided that it was worth the $6.99 to purchase the VNC module via the in-app purchasing.

    I've been using it for a few days now and it works pretty well. The hardest part is moving windows and making the dock show (I have it set to hide on the Mac Mini). The keyboard that it displays has extra keys for command, control, etc. and screen refresh is quite good. It's been nice to be able to control the TV right from the iPad and has given me a view into the future of using an iPad as a remote control for the TV.

    They have another product that helps get to your computer when you're away, but I didn't need that, so I stuck to the cheapest version.

    Pros

    • Easy to setup.
    • Decent frame rate.
    • Using it to move the mouse works well.
    • Extra keys for the keyboard are available.

    Cons

    • Dragging windows is a bit difficult.
    • Moving the mouse to the screen edge to show the dock doesn't always work.
    • Some part of the app (setup and help) could use a little polish.

    Summary

    If you have a need for a VNC client on the iPad (I haven't tried it on the iPhone, yet), the free trial should give you plenty of time to evaluate it. When I have my laptop and I'm watching TV, it is only sort of relaxing; if I have my iPad, due to limited ability to do things on it, I find I am a bit more relaxed. So, ezDesktop is definitely working well for me as it allows me to sit in front of the TV and control all aspects of my Mac Mini without having my laptop. It's worth the $6.99 for the app; the other VNC clients out there way have more bells and whistles, but ezDesktop seems to be a good fit for me.