Search code examples
iosobjective-carraysxcodeuipickerview

xcode - UIPickerView without ARC


I am testing a simple UIPickerView app so that I can use it as a class in my project... the code works beautifully with ARC but as soon as I turn ARC off the build succeeds but crashes when I click on the display of the picker...the error displayed is "EXC_BAD_ACCESS(code=2, address=oxc)" at the line

    return [pickerData1 objectAtIndex:row];

will be extremely grateful if someone can help...I have spent more than 7 working days [60hours+] trying all sorts of options given on the stackoverflow website but just can't get around the issue...needless to say I am trying to learn...

...i have learnt this much that there is a problem with the array...it is being released whereas it should be retained till the 'objectAtIndex' call...but I have tried countless ways of going about this none worked...its because i don't have an in-depth understanding of xcode as yet...trying to learn by doing...usually i am successful in figuring out how to apply sample code in my project and have successfully completed many complex parts of my project (it is an iPad app that deploys augmented reality technology), but am desperately stuck at this rather simple component...

this is the header file:

#import <UIKit/UIKit.h>

@interface PickerText : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate>
{
    NSArray *pickerData1;
}
@property (retain, nonatomic) IBOutlet UIPickerView *picker1;
@property (retain, nonatomic) IBOutlet UIButton *buttonForSelection1;
@end

and this is the implementation file

#import "PickerText.h"

@interface PickerText ()

//set tags to enable future incorporation of multiple pickers
#define kPICKER1COLUMN 1
#define kPICKER1TAG 21
#define kButton1Tag 31

@end

@implementation PickerText

@synthesize picker1;
@synthesize buttonForSelection1;

- (void)viewDidLoad
{
    [super viewDidLoad];

// assign data in array
   pickerData1 = @[@"[tap to select]", @"Item 1", @"Item 2", @"Item 3", @"Item 4", @"Item 5", @"Item 6"];

// Connect data
picker1.tag = kPICKER1TAG;
self.picker1.dataSource = self;
self.picker1.delegate = self;
picker1.hidden = YES;   
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

// set number of columns of data in picker view
- (int)numberOfComponentsInPickerView:(UIPickerView *)pickerView

{
    if (pickerView.tag == kPICKER1TAG)
        return kPICKER1COLUMN;
    else { return 0; }
}

// The number of rows of data
- (int)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

{
    if (pickerView.tag == kPICKER1TAG)
        return [pickerData1 count];
    else { return 0; }
}

// The data to return for the row and component (column) that's being passed in (ie set the data in picker view)...

//method using NSString
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{   
    if (pickerView.tag == kPICKER1TAG)
        return [pickerData1 objectAtIndex:row];
    else { return 0; }  
}

// Capture the picker view selection
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    if (pickerView.tag == kPICKER1TAG)
    {
        NSString *selection1  = [pickerData1 objectAtIndex:[picker1 selectedRowInComponent:0]];

    //check selection
    NSLog(@"%@", selection1);

    //change display text on button
    [buttonForSelection1 setTitle:selection1 forState:UIControlStateNormal];
    [buttonForSelection1 setTitle:selection1 forState:UIControlStateSelected];
    }

    //to hide picker view after selection
    pickerView.hidden=YES;      
}


- (IBAction)showPicker:(id)sender
{
    if ([sender tag] == kButton1Tag)
    {
        picker1.hidden = NO;
    }
}

@end

many thanks in advance!!


Solution

  • And in case if you want to know what the issue is with ARC turned off. The Problem is here:(1)

    @interface PickerText : UIViewController<UIPickerViewDataSource, UIPickerViewDelegate>
    {
        NSArray *pickerData1;
    }
    

    and here(2) -

    pickerData1 = @[@"[tap to select]", @"Item 1", @"Item 2", @"Item 3", @"Item 4", @"Item 5", @"Item 6"];
    

    You see, in ARC the default association is strong so when you write the second line, THE pickerData1 holds a strong reference to the autorelease array and it all works properly. But without ARC the default association is assign hence , since in line 2 you have assigned an autorelease array (which is getting released at some later point of time), you are getting the crash. You can learn the difference between assign and strong in the Apple documents.

    Better you change the array to a strong property. Though without ARC, strong will simply mean retain.

    Cheers, have fun.