2009-10-09 57 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的頂部被複位流法。它並不完美,但它比以前好得多。如果我瞭解其他事情,我會更新這篇文章。