Skip to content

Archive for

31
Jan

Animate a Blocking Dialog in iOS

Today I was faced with a little challenge when I discovered that a blocking Help Dialog which should slide on and off does not animate after the user clicks OK.

It turns out that the UIView animation is executed in a background thread and so the method that is executed when the user clicks OK is processing further without waiting for the animation to finish. Within there I will yank the view from its parent and so the animation is not shown.

The solution to this is to register an Animation Delegate as well as the method that is called when the animation is done. This is done this way:

    [UIView beginAnimations:@"hideView" context:NULL];
...
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector
        (animationDidStop:finished:context:)];

ATTENTION: Please note that these settings must be done within the animation block. Setting them outside means nothing is going to be happening.

This informs the given delegate when the animation is done and there is where I can release the block:

- (void)animationDidStop:(NSString*)animationID
                finished:(BOOL)finished
                 context:(void *)context
{
    CFRunLoopStop( CFRunLoopGetCurrent() );
}

This will do the trick and allow me to clean up the dialog meaning removing it from the super view so that it will eventually released and not become a memory leak.

This little challenge also means that I finally become some sort of a iOS crack delving deeper and deeper into regions of iOS is never dared before to even have a look at it.

Cheers – Andy

25
Jan

iPhone Crashes in the Nowhere Land

On Sunday I started to have a closer look at the memory management of the application and fully implemented the dealloc methods. Subsequent testing revealed a nasty bug where the application just died when I moved from one part of the application do another but I had not idea why it was crashing and especially where.

Well, at least I had a hunch where it was happening XCode did not point near there. Eventually I started to set breakpoints in all the dealloc methods that I could think of would be called. Eventually I saw that one property was already released and my release made it crash. So I just tried a few things and eventually found the resolution in calling the super class’ dealloc method at the end. So far I did not find any clear instruction if to call it first or last but it seems to be that way that it needs to be called last.

There are a few other things I have to keep in mind when dealing with memory management:

  • Use properties when dealing with references because it does handle re-assignments by itself
  • With properties every assignments to a property must be done with self like this: self.myProperty = …. This way we make sure that the setter method is called and subsequently the object is retained (if marked as such)
  • Called [super dealloc] as last statement in the object’s dealloc method (if provided)
  • Every object creation with alloc or new must be autoreleased when assigned to retaining property

Well, no I can go back and chase some more bugs.

-Andy

21
Jan

Adding Frameworks to XCode4

Every time I need to add a new Framework to an iPhone application on XCode4 I am dumbfounded because I don’t see how it is done. Well, I did figure it out again and so I want to make a mental note here that I don’t forget. This is done against the latest XCode4 (preview 6) and so your milage might vary.

These are the steps to accomplish that:

  1. Select the Project on the left hand side bar with the blue icon on the left
  2. Inside there select the target (left side bar inside the editor pane or just right to the project tree where we selected the project)
  3. Click on the Build Phases tab on the top
  4. Open the Link Binary with Libraries bar
  5. Click on the + button to add a new library
  6. Select the desired Framework in the pop-up dialog
  7. Now just below the project icon on the left you will see the Framework appear (with the yellow box icon)
  8. Drag the Framework onto the Frameworks Group icon (yellow folder icon) so that it is listed inside that group

Build and Enjoy.

-Andy

19
Jan

Object-C / iPhone and Switch Statements

Lately (meaning the last year or so) I started to be a lousy blogger. Either I have nothing to say or I am so busy that I don’t have time for it. So this time where I started to develop and iPhone app for hire with a hard deadline leaving a lot of work to be done. So far the project progresses well and there is little head banging. Still I ran into an old strange issue with Object-C and wasted a few hours. Eventually I dawned on my that I had this issue beforehand and then it was fixed right away.

So what happened? I wanted to create an enum to store a flag of what the program should do next like display the row, display the row’s detail or query the server for data. That looked like this:

enum Actions {
    row,
    detail,
    search
};
typedef enum Actions Actions;

Then I wanted to use it in a switch-case statement to execute the appropriate action:

switch( actions ) {
    case search:
        NSString *query = (NSString *) action.data;
        return;
    case detail:
        childViewController = [[TestViewController alloc]
              initWithNibName:@"TestDetail"
                                bundle:nil];
        break;
    default:
        NSDictionary *venue = (NSDictionary *) action.data;
        childViewController = [[Test2TableViewController alloc]
                                      initWithRows:rows];
}

But then I get this error: Expected expression before NSString which looks wrong. I am not sure why but the fix is simple. One just needs to wrap each block between case ???: and break into a {} block. That’s it:

switch( actions ) {
    case search:
        {
            NSString *query = (NSString *) action.data;
            return;
        }
    case detail:
        {
            childViewController = [[TestViewController alloc]
                  initWithNibName:@"TestDetail"
                                   bundle:nil];
        }
        break;
    default:
        {
            NSDictionary *venue = (NSDictionary *) action.data;
            childViewController = [[Test2TableViewController alloc]
                                      initWithRows:rows];
        }
}

Hope that helps - Andy