Search code examples
iosobjective-cuiactionsheet

UIActionSheet's delegate released before user input


I thinks it's best explained if I write what's happening in order:

1) object_1 creates object_2 like:

- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
      Object_2 *object_2 = [[Object_2 alloc] init];
      [object_2 show]
}

2) object_2 creates an UIActionSheet, set's itself as delegate and shows it:

- (void) show{
     UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"title"
                                                         delegate:self
                                                cancelButtonTitle:@"cancel"
                                           destructiveButtonTitle:nil
                                                otherButtonTitles:nil];
     [actionSheet showInView:[UIApplication sharedApplication].delegate.window.rootViewController.view];

}

3) the user interacts with the action sheet, and a message is sent to the delegate, the delegate has been released (by ARC). So the app crashes.

How can I "retain" it, so it exist when the delegate methods are called, and "release" it when the user is done with the action sheet (and the delegate methods)?

EDIT

Because I'm neurotic about memory management...

After some research I ended up doing this in object2:

(if you are not that into memory, guenis answer is perfectly correct)

@property (strong) MoreOptionsListController *selfPointerWhileUserInteractsWithTheMenu;

then

- (void) show {
    _selfPointerWhileUserInteractsWithTheMenu = self;
    ...
}   

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    _selfPointerWhileUserInteractsWithTheMenu = nil;
    ...
}

Solution

  • This should work:

    //Object1.h 
    //Add a property in header
    @property (nonatomic, strong) Object2 *actionSheetDelegate;
    
    //Object1.m
    //Use the property instead to retain the object
    - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
          self.actionSheetDelegate = [[Object_2 alloc] init];
          [self.actionSheetDelegate show]
    }
    

    EDIT:

    There is also an alternative way which I use a lot for uialertviews. It is to handle delegate methods with blocks. Action sheets are pretty close to alertviews in a sense, so you can use something like in this tutorial:

    http://www.cocoanetics.com/2012/06/block-based-action-sheet/