2009-10-09 61 views
0

我有一个UIPickerView。我定制它通过它的委托的viewForRow的行如下:Cocoa-Touch:UIPickerView viewForRow正在改变行命令

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 
    if (view) { 
     return view; 
    } else { 
     NSString *s = [datePickerValues objectAtIndex:row]; 

     UILabel *l = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 44)] autorelease]; 
//  l.text = s; 
     l.text = [NSString stringWithFormat:@"%@ r:%ld", s, row]; 
     l.font = [UIFont boldSystemFontOfSize:18]; 
     l.textAlignment = UITextAlignmentCenter; 
     l.backgroundColor = [UIColor purpleColor]; 
     return l; 
    } 
} 

当我周围转一下了一下,排搞混。
我甚至会得到同一行两次或更多次,有时会丢失行。行数总是在10 tho,它似乎只是调用代理的viewForRow方法,并且参数错误的参数为row

我使用row paremeter来识别行。 (如文件所述)。它有一个单一的组件,所以component参数总是0,我已经用调试器验证了这一点。

另一个奇怪的事情,根据文档,一旦我为特定行创建视图,代理的view参数将具有该视图,但使用调试器我已经看到代理的viewForRow有时被称为多次对于同一行view = nil

任何想法为什么这种奇怪的行为?我是可可和Obj-C的新手,我做错了什么?

编辑:

从文档:
view - 以前使用的此行,但隐时现,并通过选择器视图缓存的视图对象。

所以这意味着第二次为代表的特定行调用代理的viewForRow时,它将在调用1中返回视图。这是有道理的,因为这样委托人就不必重新创建视图并随着用户旋转控制而结束。
我已经验证过,实际上viewForRow被称为每次显示一行时,即使它以前显示过。

那么view参数的用法是什么?迄今为止的两个答案似乎并不合理。

回答

1

看起来问题在于UIPickerView尝试使用为了性能原因使用已经创建的视图。在这种情况下((view != nil)),您只需返回与前一行相同的视图。 如果你的观点是始终是一个UILabel你可以重写你的代码一样,(抱歉没有编译):

- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { 
    NSString *s = [datePickerValues objectAtIndex:row]; 

    UILabel *l = (view != nil)? view : [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 44)] autorelease]; 
    l.text = [NSString stringWithFormat:@"%@ r:%ld", s, row]; 
    l.font = [UIFont boldSystemFontOfSize:18]; 
    l.textAlignment = UITextAlignmentCenter; 
    l.backgroundColor = [UIColor purpleColor]; 
    return l; 
} 

它必须工作正常。

+0

是的,它在这种情况下工作,但请阅读我上面的编辑 – Prody 2009-10-09 13:48:10

+0

这只是我的猜测,但很容易检查。必须有一些术语混淆 - 您的选取器(和数据源)中的实际行以及选取器显示的行。因此,在第二个定义中,标准选取器只有7行 - 5个可见,2个用于滚动目的。我添加了NSLog消息 - UIPicker为我创建了7个视图。 但我同意文档在这一点上显得有点混乱。 – Vladimir 2009-10-09 14:02:10

2

每次调用此方法时都必须更新视图中的数据。通过不更新,您将返回陈旧/重复的数据。

+0

请阅读我的上述编辑 – Prody 2009-10-09 13:47:38

+0

我有一个类似的问题 - 当视图被加载时,我选择了一行(这是不可见的)。组件的加载显示为错误的索引,但那些'不正确'的索引然后被重新加载,并且我正在重写数据,所以它们从未得到正确的行数据。 – shortstuffsushi 2012-11-23 05:05:41

0

我看到这是一个非常古老的问题,但我与iOS7有同样的问题,无法找到满意的答案。当我试图从viewForRow委托方法中敲入'row'参数时,它会返回不正确的值并混合起来。

我能够通过执行以下操作来解决这个问题,

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

    //Create a label 
    //Set a tag for label 
    //Add label to view as a subview 
    //return view 

if (component == 1) { 
    view = [[UIView alloc] init]; 
    view.backgroundColor = [UIColor clearColor]; 
    correctRowLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 30, 20)]; 
    [correctRowLabel setText:[NSString stringWithFormat:@"%li", row]]; 
    [correctRowLabel setTag:100]; 
    [view addSubview: correctRowLabel]; 
    return view; 
    } 

该组件安装后根据需要,在viewForRow委托方法的开始,执行下列查看正确的行值,

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

    UILabel* correctRow = (UILabel*)[pickerView viewWithTag:100]; 
    NSInteger correctRowValue = [correctRow.text integerValue]; 
    NSLog(@"Correct row is: %li",correctRowValue); 
    UILabel* correctRowLabel = nil; 

... 

编辑:

我想补充一点,rowHeightForComponent必须设置为默认值和标签必须在viewForR的顶部被复位流法。它并不完美,但它比以前好得多。如果我了解其他事情,我会更新这篇文章。