Badminton on Rails
RSS icon Home icon
  • ARC Conversions Explained – Part 3 of 3

    Posted on May 2nd, 2012 Raymond Law No comments

    In Part 2, I talked about the removal of retain, release, and autorelease. The ARC conversion tool also removes:

    - (void)dealloc
    {
        [super dealloc];
    }

    Since ARC handles memory management for us, we no longer need to explicitly call release. Since most of the time the dealloc method is used to release memory. The dealloc method can be removed. The chaining to super is automated and enforced by the compiler.

    Toll-Free Bridging

    Toll-Free Bridging means you can cast an object between Objective-C and Core Foundation freely, as long as you call retain and release/autorelease properly.However, with ARC doing memory management for us, we do not call these methods directly. Therefore, when we cast an object between Objective-C and Core Foundation, we need to tell ARC what to do when the object is no longer needed.

    __bridge
    __bridge_transfer   CFBridgingRelease
    __bridge_retained   CFBridgingRetain    CFRelease
    • When changing ownership from Core Foundation to Objective-C, you use CFBridgingRelease().
    • When changing ownership from Objective-C to Core Foundation, you use CFBridgingRetain().
    • When you want to use one type temporarily as if it were another without ownership change, you use __bridge.

  • ARC Conversions Explained – Part 2 of 3

    Posted on April 25th, 2012 Raymond Law 2 comments

    In Part 1, I mentioned that ARC allows us to focus on application code rather than thinking about having to call retain, release, and autorelease. ARC makes the following changes:

    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
     
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];

    In a project, there is the default autorelease pool that gets created in main.m:

    int main(int argc, char *argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        int retVal = UIApplicationMain(argc, argv, nil, nil);
        [pool release];
        return retVal;
    }

    Your application is called to work with the call to UIApplicationMain:

    int retVal = UIApplicationMain(argc, argv, nil, nil);

    The return value of the running of your application is used as the return value of the main function. This makes sense.

    What about the lines regarding the pool? It turns out that objects created in the code between the creation and destruction of the NSAutoreleasePool will use that wrapping NSAutoreleasePool to auto-release objects when they are no longer needed. You do this by calling the autorelease method on the object. Since ARC handles memory management for us, we don’t need to autorelease objects anymore. Therefore, taking out the call to autorelease will just do the trick here.

    The same thing goes for retain and release. The ARC conversion tool suggests removing:

    [label release];

    When we specified our property, we changed it from retain to strong to indicate that we intend to use the property as a strong pointer, but we do not increment its reference count. To balance things out, we do not decrement its reference count either. Therefore, the call to release is not needed.

    In fact, ARC would not even compile if it sees that you call retain, release, or autorelease. You will never forget to take this out if you are using ARC.

    TIP #1:

    Almost every project creates its default NSAutoreleasePool in main.m, but you can also create your own NSAutoreleasePool if necessary. I’ve never had to do this, so I can’t say I am an expert. I will just point to the NSAutoreleasePool class reference which describes when and how you should do this. Specifically, it says:

    The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop, and drains it at the end, thereby releasing any autoreleased objects generated while processing an event. If you use the Application Kit, you therefore typically don’t have to create your own pools. If your application creates a lot of temporary autoreleased objects within the event loop, however, it may be beneficial to create “local” autorelease pools to help to minimize the peak memory footprint.

    It’s good to know that the option is there if you application uses a lot of memory and you need to deal with it in a more effective manner. I brought this up because the syntax of using an NSAutoreleasePool has changed from:

    int main(int argc, char *argv[]) {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        int retVal = UIApplicationMain(argc, argv, nil, nil);
        [pool release];
        return retVal;
    }

    to:

    int main(int argc, char *argv[]) {
        @autoreleasepool {
            int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
            return retVal;
        }
    }

    The alloc-init-release has been replaced by @autoreleasepool { … }.

    TIP #2:

    The above snippet also shows another subtle difference between a project created in Xcode 4.2 and previous versions.

    The AppDelegate inherits from NSObject in older Xcode, but it now inherits from UIResponder in Xcode 4.2.

    @interface AppDelegate : NSObject <UIApplicationDelegate>
     
    @interface AppDelegate : UIResponder <UIApplicationDelegate>

    When you create a new project in Xcode 4.2, the AppDelegate inherits from UIResponder instead of NSObject. This is necessary if you check the box that says Use Storyboard, which is another new Xcode feature that makes your application flow clearer to help you developing your application. Inheriting from UIResponder makes the AppDelegate eligible to respond to events.

    Converting to Storyboards Release Notes says:

    The application delegate is responsible for loading the storyboard and managing the window. You need to specify the name of the application delegate class in UIApplicationMain, and ensure that the application delegate has a property called window.

    If you use Storyboard, make sure your AppDelegate does that, and pass the class name of AppDelegate to UIApplicationMain. If you are using individual Xibs, you can still inherit from NSObject and pass nil.

    In Part 3, I will explain what you need to do when you use Objective-C and Core Foundation interchangeably.

  • ARC Conversions Explained – Part 1 of 3

    Posted on April 18th, 2012 Raymond Law 1 comment

    The iOS SDK from Apple introduces Automatic Reference Counting (ARC). You can now stop thinking about all those retain, release, and autorelease, so that you can focus on the code instead of memory management. ARC is available if you use the new and better LLVM 3.0 compiler. If you create a new project in Xcode 4.2, these are already used as defaults. For old projects created with previous versions of Xcode, you can choose Edit > Refactor > Convert to Objective-C ARC to ask Xcode to update all or some of your source files to use ARC. This means you can use ARC for application specific files but still use manual memory management for old libraries you developed or third-party libraries.

    This sounds great, but there are always caveats as we all know it. The fact that the iOS SDK consists of both Objective-C and C libraries (e.g. Address Book, Core Foundation, Core Image, Core Graphics, …etc.) means we really need to have a good understanding of how manual memory management works to use ARC effectively.

    When you use Edit > Refactor > Convert to Objective-C ARC, Xcode shows the changes it is about to make in a diff view. Instead of just clicking the Save button and let Xcode to update the sources. Let’s try to understand the changes it is trying to make, so that we won’t be surprised when the app fails to build or crash when run.

    @property (nonatomic, retain) IBOutlet UILabel *label;
     
    @property (nonatomic, strong) IBOutlet UILabel *label;

    What is the difference between retain and strong?

    A retain property says to the compiler that the property should increment the reference count by 1 when it is set to an object. When you no longer needs the object, you need to call release on it before setting it to a new object. This is manual memory management.

    A strong property means the property is a strong pointer to an object. If pointer A is a strong pointer and both pointers A and B point to the same object, when pointer B points is set to point to something else. Pointer A is still valid because it keeps a reference to the object it points to. However, if pointer A is a weak pointer, when pointer B is set to point to something else, pointer A becomes nil because it is too weak to keep the object alive.

    What does this mean with ARC? A retain property should only be used when you are not using ARC, since you are expected to call release when you no longer needs the object the property points to. However, ARC handles calling release for us when it compiles, that means we are not supposed to call retain and in fact we cannot because the compiler would complain. Therefore, we tell ARC that the property is a strong property so when ARC detects it is no longer needed, it can release it for us.

    If we were to declare the property as a weak property, since weak pointers do not keep the object alive, when it is set to point to an object and if it is the only pointer that points to that object, it will not hold the object, and we would get a crash.

    As you can see, while ARC can help us handle most memory management and free us to develop the application. It does not mean we don’t need to understand memory management. In future episodes of this ARC series, I will point out more caveats of using ARC and what we need to understand deeper in order to use it correctly and effectively.

    TIP #1:

    You can create a strong pointer using:

    NSString *version = @"iPhone 4S";
    __strong NSString *strongVersion = version;

    or just:

    NSString *version = @"iPhone 4S";
    NSString *strongVersion = version;

    since variables are strong by default. When you call [version release], strongVersion is still valid.

    You create a weak pointer using:

    NSString *version = @"iPhone 4S";
    __weak NSString *weakVersion = version;

    When you call [version release], weakVersion becomes nil.

    TIP #2:

    You need to create delegate property as a weak property, like so:

    @interface MyViewController : UIViewController
    @property (nonatomic, weak) id <MyDelegate> delegate;
    @end

    This is important. If we were to declare the delegate as a strong property, when an object of MyViewController is created, it has a strong pointer to the MyDelegate delegate, and the MyDelegate delegate also has a strong pointer to the MyViewController object. When MyViewController is released, it needs to release MyDelegate. When MyDelegate is released, it needs to release MyViewController. It is a never-ending cycle! Therefore, we need to make MyDelegate a weak pointer to MyViewController so that they can be properly released.

    In Part 2, I will explain retain, release, and autorelease and why they aren’t needed anymore when you use ARC.

  • New Apple products

    Posted on September 7th, 2007 Raymond Law No comments

    Apple announced quite a few new products for the holiday season a couple days ago. The iPod nano with a widescreen for video and the iPod touch seem to garner the most attention. I am not a big on-the-go music fan and I don’t own an iPod and can really use the iPod touch with the cool touch screen interface. It also has Safari built in so I can browse over wi-fi. It works just like the iPhone and who doesn’t love the iPhone?

    However, after some more thoughts, if I can only use Safari when I am in a wi-fi hotspot, what’s the point if I already plan to get myself a macbook? The only difference would be the touch screen UI, but is it really better than a macbook’s UI, with a keyboard and a mouse? No. Touch screen is cool but the iPod touch is just for play. I ain’t gonna shell out $299 or $399 for something that I can do better with a macbook.

    What would be really cool is some 3rd party developers write a Skype app that can appear as an icon on the iPhone or iPod touch so I can totally bypass the cellular network when I have city-wide wi-fi access. Then I can save some cell phone bills.

    Oh, a larger capacity with both flash and hard drive would be a nice addition as 16GB is really not enough nowadays. The iPod nano does have a 160GB option. I guess you can’t get ‘em all in one…

  • iPhone drag and drop

    Posted on July 15th, 2007 Raymond Law 1 comment

    I had a chance to play with the iPhone at an Apple store yesterday. I found that if you go to Google Map or any Google Map mashup in Safari, you can’t drag the map! This is because the iPhone interprets your finger dragging as dragging the web page, not the Google Map on the web page.

    The Google Map integrated into the iPhone itself works great though. Is this a bug or am I just missing something? Hopefully Apple fixes this soon because this means all websites that have drag and drop like Ta-da list are not usable (though I have not tried Ta-da list on the iPhone).

    Update: Just headed over to the iPhone Developer Site. According to Apple’s Web Development Guidelines:

    “A few other things to keep in mind about fingers as an input device:
    * There are no gestures to perform cut, copy, paste, drag-and-drop, and text selection operations.
    * The width of a finger limits the density of links on a page. If the links are too close, your users won’t be able to choose a single one.”

    So the answer is no, at least for now.