London guy
London guy

Reputation: 28032

How do I solve this Automatic Reference Counting (ARC) conflict?

I have a UIViewController that requires the Facebook login button to be present in the screen. Now, Facebook iOS button requires the ARC to be OFF.

On the other hand, in the same UIViewController I am using NSTimer to show few photos as a slideshow at the background - this feature requires ARC setting.

So, I have a single file that requires ARC for one of the components, while not for other.

The exact problem is in this code:

-(void)handleTimer {

    [UIView transitionWithView:imageView duration:3 options:(UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionCurveEaseInOut) animations:^{
        imageView.image = [UIImage imageNamed:[myImages objectAtIndex:imagePtr]];
    } completion:nil];

    if(imagePtr == (myImages.count) - 1)
        imagePtr = 0;
    else
        imagePtr = imagePtr + 1;
}

If I disable ARC for the file that has this code, it throws an error at this line:

imageView.image = [UIImage imageNamed:[myImages objectAtIndex:imagePtr]];

The error reads:

Thread 1 : EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

Actually, I have a time as you see above, to continuously update the image in imageView.

myImageView is of type

@property (nonatomic, assign) IBOutlet UIImageView *imageView;

So, what is the problem here?

Here is how myImages are initialized in viewDidLoad() method:

@interface ViewController () {
    UIImage *nextImage;
    NSArray *myImages;
    int imagePtr;
}
@end

@implementation ViewController
@synthesize imageView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    myImages = @[@"image1.jpg", @"image2.jpg", @"image3.jpg", @"image4.jpg", @"image5.jpg", @"image6.jpg", @"image7.jpg", @"image8.jpg", @"image9.jpg",
                 @"image10.jpg", @"image11.jpg", @"image12.jpg", @"image13.jpg",
                 @"image14.jpg", @"image15.jpg", @"image16.jpg", @"image17.jpg",
                 @"image18.jpg", @"image19.jpg", ];
    imagePtr = 0;

    NSTimer *timer;

    imageView.image = [UIImage imageNamed:[myImages objectAtIndex:imagePtr]];
    imagePtr = imagePtr + 1;

    //imageView.image = [UIImage imageNamed:[myImages objectAtIndex:imagePtr]];

    timer = [NSTimer scheduledTimerWithTimeInterval: 3
                                             target: self
                                           selector: @selector(handleTimer)
                                           userInfo: nil
                                            repeats: YES];

    // Do any additional setup after loading the view, typically from a nib.
}

Upvotes: 0

Views: 249

Answers (1)

Sulthan
Sulthan

Reputation: 130172

Your controller is probably compiled under MRC. That means that your ivars doesn't retain values you assign to them, for example:

myImages = @[...];

Will assign the pointer but the array will get released anyway and when you try to access myImages later, the application will crash.

Solutions:

  1. MRC - with retain
    When assigning to the ivars, retain the value explicitly (myImages = [@[...] retain];), don't forget to release in your -dealloc.

  2. MRC - with properties
    Remove your ivars and declare them as properties

    @property (nonatomic, retain) NSArray *myImages;

    ... self.myImages = @[...];


    Again, don't forget to release your array in -dealloc

  3. ARC (the preferred solution) - compile your controller with ARC and the values in ivars will be implicitly __strong and retained for you.

Upvotes: 1

Related Questions