0

I am using a UIPickerView in a viewcontroller that is in a modal view(if that's what it's called). I've read everywhere that [picker reloadAllComponents]; in viewDidLoad should do the trick, but it doesn't. I have overridden the -(UIView*)viewForRow-method, but I don't think that should be the problem..

The thing is, when the viewController pops up vertically, the picker is empty. And it stays empty until I scroll down so that a new row can appear. However, if I add [picker reloadAllComponents]; to viewDidAppear, then the data shows up immediately after the viewController has completed it's intro-animation(vertically). This is annoying though. I want the picker to already have it's data when it slides up.

I tried putting reloadAllComponents in both viewDidLoad and viewWillAppear, but it won't work.

I put an NSLog in the delegate method, and it prints out correct data, and it does it before the view pops up, but why doesn't it show it?

I have had the same problem with tableViewController before, and I think reloadData did the trick then, but why won't it draw my views in viewDidLoad? It only does it if it's called in viewDIDappear..

Code:

-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if(component == TYPE1)
        return [[con getTypes] count];

    else return 1;

}
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    UIView* newView = [[UIView alloc] init];

    //Create a label, put it on the left side of the view
    UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(view.frame.origin.x + 5, view.frame.origin.y, view.frame.size.width-45, view.frame.size.height)];
    [label setText:[[[con getTypes] objectAtIndex:row] getName]];
    [newView addSubview:label];//add

    //Create an imageview, put it on the right side of the view
    UIImageView*imageViewType = [[UIImageView alloc] initWithFrame:CGRectMake(view.frame.origin.x+(view.frame.size.width-40), view.frame.origin.y, 40, 40)];
    [imageViewType setImage:[[[con getTypes] objectAtIndex:row] getImage]];
    [newView addSubview:imageViewType];//add

    [label setBackgroundColor:[UIColor clearColor]];


    NSLog(@"%@", [[[con getTypes]objectAtIndex:row] getName]);
    //This NSLog prints out the correct name for the top three items of the list
    //-even when called from viewDidLoad, and even before the view appears, but
    //the content never shows up in the picker unless I scroll or call it again in 
    //viewDidAppear..

    return newView;
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Sti
  • 8,275
  • 9
  • 62
  • 124
  • What are you loading into the UIPicker, NSMutableArray? If so, when do items get added to the array? – JDx Apr 26 '13 at 10:59
  • @JDx An NSMutableArray with some objects. I create this viewController programmatically and use `initWithController:(Controller*)c`(self made), and the controller contains the mutable array already. In my init-method, I use `self = [storyboard instantiateViewControllerWithIdentifier:@"identifier"];` and then set the data, is this the problem?.. I don't think so.. When I call `reloadAllComponents` from `viewDidLoad` it prints out correct text(the text as the picker should be showing), but it won't display it until I scroll down for the delegate to kick in or something.. – Sti Apr 26 '13 at 11:05
  • Please show the code of your overwritten viewForRow and your implementation of – numberOfComponentsInPickerView: and – pickerView:numberOfRowsInComponent: – Hermann Klecker Apr 26 '13 at 11:11
  • @HermannKlecker code added.. Is it because I'm not using the provided `UIView *view` in the viewForRow? I thought that was like a reuse, I might be wrong.. – Sti Apr 26 '13 at 11:21
  • Strange. This should work. Is the method called at all? If not the the delegate is probably not set properly. – Hermann Klecker Apr 26 '13 at 14:14
  • However, you should not create a new view on every call. Only create a new one when the used one handed in is nil. When you re-use the old one then either remove all its subviews or reuse the subviews too. In your case I would re-use the sub views. Though, this does not solve your problem. – Hermann Klecker Apr 26 '13 at 14:17
  • You use view.frame.origin regardless wether view is nil nor not. For the first calls it will be nil because notthing is being reused. On the second call there are already views, the ones that you created before. And for those view.frame.origin carries some reasonalbe value, that is (0,0) I guess. When view is nil then therre is an unpredicatble value in the origin. Meaning your view IS displayed but the label and graphic are located somewhere else. I'll try to scatch some code base on yours. – Hermann Klecker Apr 26 '13 at 14:23

1 Answers1

1
-(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    UIView* newView;

    if (view) 
       newView = view;
    else { 
       newView = [[UIView alloc] initWithFrame:CGRectMake(0,0,250,50)];  // use some appropriate size hier. I just made some figures up which almost certainly will not work. 
      //Create a label, put it on the left side of the view
      UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(5.0f, 0.0f, newView.frame.size.width-45, newView.frame.size.height)];
      [newView addSubview:label];//add

    //Create an imageview, put it on the right side of the view
      UIImageView*imageViewType = [[UIImageView alloc] initWithFrame:CGRectMake((newView.frame.size.width-40.0f), 0.0f, 40.0f, 40.0f)];
      [newView addSubview:imageViewType];//add
    }

    [label setText:[[[con getTypes] objectAtIndex:row] getName]];
    [label setBackgroundColor:[UIColor clearColor]];

    [imageViewType setImage:[[[con getTypes] objectAtIndex:row] getImage]];

    return newView;
}
Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • Thank you! It works now. I had to fix the code up a bit, for example, `[label setText]` is unreachable after the if-statement, so if anyone else are wondering, I got a hold of them by `UILabel *label=(UILabel*)[[newView subviews]objectAtIndex:0];´. `0` for the label, `1` for the imageView. The tricky part was that that wasn't enough! Even though the data is set after the if-statement, apparently it doesn't get set for when view=nil. So by putting `[label setText]` and `setImage` in the `else` as well, it finally worked. And the sizes I ended up using were `(15, 6, 140, 44)`. Thanks again! – Sti Apr 26 '13 at 18:08
  • Though.. when I think about it.. It seems strange to me that the rest of the rows appeared correct after scrolling when I never really did set the frame.. Fishy.. – Sti Apr 26 '13 at 18:12
  • You init with a frame. That corresponds to initializing and setting a frame in two steps. Unless the frame changes, which it does not, as far as I can see, there is no need to re-set the frame. The frames remain unchanged when a superview (here the cell) scrolls off screen. – Hermann Klecker Apr 29 '13 at 07:22