views:

1752

answers:

4

I find that randomly I get a EXC_BAD_ACCESS error on the iPhone when updating the status. This occurs pretty randomly.

Anyone have any idea to how this make be fixed?

#import "TwitterViewController.h"

NSString *_testUID = nil;
NSString *sImageName;

@implementation TwitterViewController

//Turns NSLogs into comments
//#define NSLog //

- (void)viewDidLoad {

    self.title = @"Twitter";

    arrayEmotes = [[NSMutableArray alloc] init];
    [arrayEmotes addObject:@"Happy"];
    [arrayEmotes addObject:@"Sad"];
    [arrayEmotes addObject:@"Tongue"];
    [arrayEmotes addObject:@"Drunk"];
    [arrayEmotes addObject:@"Bored"];
    [arrayEmotes addObject:@"Love"];
    [arrayEmotes addObject:@"Sleepy"];
    [arrayEmotes addObject:@"Sick"];
    [arrayEmotes addObject:@"Awake"];
    [arrayEmotes addObject:@"Shocked"];
    [arrayEmotes addObject:@"Angry"];
    [arrayEmotes addObject:@"Laughing"];
    [arrayEmotes addObject:@"Dancing"];
    [arrayEmotes addObject:@"Confused"];

    [activityView startAnimating];
    [currentActivity setText:@"Logging In"];

    NSString *username = [[NSUserDefaults standardUserDefaults] stringForKey:@"username_preference"];
    NSString *password = [[NSUserDefaults standardUserDefaults] stringForKey:@"password_preference"];

    // Make sure you entered your login details before running this code... ;)
    if ([username isEqualToString:@""] || [password isEqualToString:@""]) {
     //Show the UIAlert if no username or password is stored in the settings
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Incorrect username/password stored in the settings." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
     [alert show];
     [alert release];  
        NSLog(@"You forgot to specify your username/password in settings.bundle!");
    }

    // Create a TwitterEngine and set our login details.
    twitterEngine = [[[MGTwitterEngine alloc] initWithDelegate:self] retain];
    [twitterEngine setUsername:username password:password];

    // Get updates from people the authenticated user follows.
    //[twitterEngine getFollowedTimelineFor:username since:nil startingAtPage:0];
    _testUID = [twitterEngine testService];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
    return 1;
}


- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
    return [arrayEmotes count];
}

- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    return [arrayEmotes objectAtIndex:row];
}

- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    NSLog(@"Selected Color: %@. Index of selected color: %i", [arrayEmotes objectAtIndex:row], row);
    [btnUpdateMood setEnabled:YES];
}

- (IBAction)updateMood:(id)sender
{   

    NSLog(@"Tried to send status.");

    NSInteger selectedindex = [pickerView selectedRowInComponent:0];
    switch(selectedindex){
     case 0:
      //Happy
      sImageName = @"Happy";
      break;
     case 1:
      //Sad
      sImageName = @"Sad";
      break;
     case 2:
      //Tongue
      sImageName = @"Tounge";
      break;
     case 3:
      //Drunk
      sImageName = @"Drunk";
      break;
     case 4:
      //Bored
      sImageName = @"Bored";
      break;
     case 5:
      //Love
      sImageName = @"Love";
      break;
     case 6:
      //Sleepy
      sImageName = @"Sleepy";
      break;
     case 7:
      //Sick
      sImageName = @"Sick";
      break;
     case 8:
      //Awake
      sImageName = @"Awake";
      break;
     case 9:
      //Shocked
      sImageName = @"Shocked";
      break;
     case 10:
      //Angry
      sImageName = @"Angry";   
      break;
     case 11:
      //Laughing
      sImageName = @"Laughing";   
      break;
     case 12:
      //Dancing
      sImageName = @"Dancing";
      break;
     case 13:
      //Confused
      sImageName = @"Confused";
      break;
     default: break;
    } 

    [twitterEngine sendUpdate:[@"has changed his/her iMood to " stringByAppendingString:sImageName]];

}


// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}


- (void)dealloc {
    //Releasing seems to sometimes cause complete errors.
    //[twitterEngine release];
    [super dealloc];
}

#pragma mark MGTwitterEngineDelegate methods


- (void)requestSucceeded:(NSString *)requestIdentifier
{
    [activityView stopAnimating];

    //Some animations
    [UIView beginAnimations:@"redToWhite" context:nil];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:1];
    [UIView setAnimationRepeatCount:0];

    //Change background colour of the activity area over 1 second
    [activityArea setBackgroundColor:[UIColor whiteColor]];
    [currentActivity setText:@"Logged In"];

    [UIView commitAnimations];
    //End of animations

    NSLog(@"Request succeeded (%@)", requestIdentifier);

    if ([requestIdentifier isEqualToString:_testUID])
    {
     NSLog(@"[TWITTER UP]");
    }

}


- (void)requestFailed:(NSString *)requestIdentifier withError:(NSError *)error
{

    currentActivity.text = [NSString stringWithFormat:@"Error: %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSErrorFailingURLStringKey]];
    NSLog(@"Twitter request failed! (%@) Error: %@ (%@)", 
          requestIdentifier, 
          [error localizedDescription], 
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);

}


- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)identifier
{
    NSLog(@"Got statuses:\r%@", statuses);
}


- (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)identifier
{

    NSLog(@"Got direct messages:\r%@", messages);
}


- (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)identifier
{
    NSLog(@"Got user info:\r%@", userInfo);
}


- (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString *)identifier
{
    NSLog(@"Got misc info:\r%@", miscInfo);
}


- (void)imageReceived:(UIImage *)image forRequest:(NSString *)identifier
{
    NSLog(@"Got an image: %@", image);
}




@end
A: 

Anytime you have an EXC_BAD_ACCESS error, it's always a retain/release problem. Your code also has at least one leak (look where you're creating the twitterengine).

I suggest you read Cocoa Memory Management Rules. They'll help you find the issue.

August
Why, what have i done wrong around that bit?
Domness
+1  A: 

You have a few leaks (twitterEngine (you are retaining it when alloc/init does the job fine) and arrayEmotes (never gets released) to name the two I spotted right away), and you could have another issue related to sImageName when you send the update (notice how it isn't defined on a scope other than inside the switch statement - I don't really know if this would definitely cause issues, it's just something I always try to avoid. I can see it potentially causing an EXC_BAD_ACCESS).

Anyway, try using GDB to step through your program to figure out what object exactly is being released early. A lot of headaches can be solved simply with GDB.

Joel Levin
A: 

I'm having this issue too, and it's weird; even though I am cleaning up my MGTwitterEngine object properly, one of its callbacks is still getting called after I release the object. This is causing some sort of access violation when the callback is somehow called from the dead.

[twitter closeAllConnections] might work?
Domness
A: 

@Vargonian: releasing an object does not mean that the object will also be destroyed immediately. The object (in this case the twitter engine) might still be retained by some other object which is not under your control. That's why it is still possible that the twitter engine will call its delegate.

If you're gonna destroy the delegate object, you should explicitly reset the twitter engine's delegate property before:

[twitterEngine setDelegate:nil];

Snafuuz