Pregunta

first here is my code:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.elements = [NSMutableArray arrayWithObjects:@"Object 1", @"Object 2", @"Object 3", nil];
    self.elements2 = @"Lorem ipsum";
    NSLog(@"%@", self.elements);

    [self loadContent];
}

He prints, that _elements is correctly initialized also after loadContent, _elements contains three objects. But only a few lines later in the method numberOfComponentsInPickerView:, which is called directly after the viewDidLoad method, _elements is nil. I don't know why my app is settings _elements to nil?

Thanks iComputerfreak


Edit

I uploaded my full code to gist.github: https://gist.github.com/iComputerfreak/fa3d3ee925c45cd6e1f2


Console Output

Okay here my console output:

// in viewDidLoad (after setting): 
2014-05-13 16:56:14.292 HFG Vertretungsplan[1051:60b] (
    "Object 1",
    "Object 2",
    "Object 3"
)
// numberOfComponents called automatically:
2014-05-13 16:56:14.298 HFG Vertretungsplan[1051:60b] numberOfComponentsInPickerView: (null)
2014-05-13 16:56:14.303 HFG Vertretungsplan[1051:60b] numberOfComponentsInPickerView: (null)
// viewWillAppear method reached:
2014-05-13 16:56:14.306 HFG Vertretungsplan[1051:60b] View will appear
2014-05-13 16:56:14.306 HFG Vertretungsplan[1051:60b] Elements in viewWillAppear: ( // NSLog("%@", self.elements);
    "Object 1",
    "Object 2",
    "Object 3"
)
// [self.elementsPicker reloadAllComponents];
2014-05-13 16:56:14.307 HFG Vertretungsplan[1051:60b] numberOfComponentsInPickerView: (null)
2014-05-13 16:56:14.308 HFG Vertretungsplan[1051:60b] Elements after reloadAllComponents: (
    "Object 1",
    "Object 2",
    "Object 3"
)

So only while reloading the components is elements nil. Before and after that, it has content.

¿Fue útil?

Solución 2

I usually make headers like this:

#import <UIKit/UIKit.h>

@interface SettingsViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>

@property (nonatomic, weak) IBOutlet UITextField *userTextField;
@property (nonatomic, weak) IBOutlet UITextField *passwordTextField;
@property (nonatomic, strong) IBOutlet UIPickerView *elementPicker; // I would suggest to use sttong for outlets if you are planning to move them out of their superview
//@property (nonatomic, retain) NSMutableArray *elements; // if you use ARC I would suggest to forget about retain in favor of strong.
@property (nonatomic, strong) NSMutableArray *elements;
//@property NSString *elements2; // I would suggest not to rely on implicit property specifier declarations in favor of more verbosity
@property (nonatomic, strong) NSString *elements2;


- (IBAction)userOrPasswordChanged:(id)sender;

@end

Then in .h or .m file you don't need to declare _elements (or elements) one more time since it is automatically created with property declaration. If you need to declare it (it is needed in some cases) you should be careful and read about naming convention.

With such header the original questions problem should be solved unless you do something extravagant in your remaining code.

EDIT: I have dug a bit in topic starter's real code. The problem is that he has 2 instances of SettingsViewController. They are both set in his storyboard. screenshot of storyboard

so one of the instances is used to be presented to screen and thus viewDidLoad method is called and _elements is populated and another is created silently by storyboard and used as the instance used as datasource and delegate of UIPickerView. The second instance is not shown so its viewDidLoad method is not called and _elements are nil.

So if you print self along with elements you will see the difference.

If you remove the second instance in the picture you will get everything working.

Otros consejos

override your _elements getter

- (NSMutableArray *)elements
{
    if (!_elements)
        _elements = [[NSMutableArray alloc] init];
    return _elements;
}

and first time call _elements like

self.elements

it should be like this on strong objects

whenever you retain the the object you should use self.yourObject

self.elements = [NSMutableArray arrayWithObjects:@"Object 1", @"Object 2", @"Object 3", nil];

"elements" should be strong or retain pointer in .h files

Try doing all of these things.

At the place where you have defined the NSMutableArray property, make sure it is nonatomic and retain

@property(nonatomic, retain) NSMutableArray* elements;

In the .m file do:

@synthesize elements;

Always access it using self like this:

self.elements = [NSMutableArray arrayWithObjects:@"Object 1", @"Object 2", @"Object 3", nil];

and preferably whenever you are allocating the array, try to use it like this

[self setElements: array2];

instead of

elements = array2;

or

self.elements = array2;

dangling pointers

I took a look at your project and I am wondering this, why are you using 2 instances of elements array? Because in the modern runtime only one instance is needed.

I prefer to declare objects on properties because I think it makes the memory management of the objects loaded from the nib much clearer. Take a look at memory management of nib objects and I think you will see what I mean.

Possible solution

Try to reload your pickerView after self.elements is created and has objects in it.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top