KVISH
KVISH

Reputation: 13198

UIAlertView on main queue crashing.

I have an issue showing a UIAlertView on the main thread. I'm not sure why but it keeps crashing, despite me running on the main thread. The following block is on the background thread, but I have the alert on the main as below:

void (^removeFromCalendar)(NSString *, NSString *, EKEventStore *) = ^(NSString *error, NSString *eventKey, EKEventStore *eventDB) {
    EKEvent *myEvent = [eventDB eventWithIdentifier:eventKey];
    NSError *err = noErr;

    if(myEvent != NULL && myEvent != (id)[NSNull null]) {
        [eventDB removeEvent:myEvent span:EKSpanThisEvent error:&err];
    } else {

        // Event was not found, nothing to do
        return;
    }

    [eventDB release];

    if (!err || err == noErr) {
        NSLog(@"Deleted event %@", myEvent.title);

        // Show alert on the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            // Showing the alert for unattending
            NSString *resultString = @"This event was removed from your calendar.";
            UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Info" message:resultString delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil] autorelease];
            [alert show];
        });

        return;
    }

    error = err.description;
};

If I comment out the bottom where it shows the alert, everything is fine. But for the alert, I keep getting a EXC_BAD_ACCESS error. Can somebody explain why? It's on the correct thread, and I cant for the life of me understand where the memory issue could come from!

Upvotes: 2

Views: 1466

Answers (3)

Owen Hartnett
Owen Hartnett

Reputation: 5935

Instead of using dispatch_async, why not use the objective C call:

[self performSelectorOnMainThread

You might have to package it up in its own method. Alternatively, call it using:

[self performSelector:@selector(myAlertMethod) withObject:nil afterDelay:0.25]

These methods have been tried and true since day 1.

Upvotes: 0

Sandeep
Sandeep

Reputation: 21154

May be you view is being released when you finish until you finish with the background queue. So, for safety why dont you use it like this;

...........
  UIViewController __weak *myController = self;
 dispathch_async(backgroundQueue, ^{ 
   UIViewController __strong *myStrongController = myController;
 ...............
 dispatch_async(dispatch_get_main_queue(), ^{
            if(myStrongController){
            // Showing the alert for unattending
            NSString *resultString = @"This event was removed from your calendar.";
            UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Info" message:resultString delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil] autorelease];
            [alert show];
            }
        });
}).

Upvotes: 1

Maximilian Litteral
Maximilian Litteral

Reputation: 3089

This is how you present an alert view:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"<#(NSString *)#>" message:@"<#(NSString *)#>" delegate:self cancelButtonTitle:@"<#(NSString *)#>" otherButtonTitles:nil];
    [alert show];
    [alert release];

Upvotes: 0

Related Questions