使用UIPickerView显示数据

本文详细探讨了在iOS应用中使用UIPickerView显示7个组件,并针对每个组件的文本居中对齐及不同颜色的需求进行了实现。通过三种方案对比分析,最终解决了模板数组中的UILabel对象无法进行深度复制的问题,确保了每个组件独立显示所需内容而不相互干扰。文章还介绍了创建UILabel存入DataSource数组的方法,以及如何根据组件编号动态返回相应数据对象,同时提供了性能优化的实现思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近学习UIPickerView使用,练习时候想遇到些问题,总结一下。

用UIPickerView 显示7个组件,每个组件中的数据要居中对齐,1-6组件中字体颜色为红色,7组件中字体颜色为蓝色。

在控制器中创建两个实例变量:

UIPickerView *picker; 

NSArray *datasourceArray; //用做数据源

因为UIPickerView中的文本不能设置颜色和对齐方式,所以delegate使用UILabel显示文本,并使用返回视图(UIView *)的方法:

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

有三种方案可供选择:

1.不需要创建实例变量,直接在Delegate方法中创建UILabel,设置属性,并返回。

2.在初始化时,创建模板可变数组,并根据最大组件的总行数,把Label控件插入此可变数组中,再把此模板数组赋值给 dataSource。最后Delegate调用方法返回模板数组中的相应行的对象。

3.创建7个数组的实例变量,分别作为picker每个组件的数据源,再创建相应数量的UILabel,分别设置好。最后Delegate调用方法返回相应数据源中的对象。

01 //实现第1方案:
02 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
03  
04     UILabel *showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f,0.0f,20.0f,20.0f)];
05  
06     showLabel.text = [NSString stringWithFormat:@"%d",row+1];
07     showLabel.backgroundColor = [UIColor clearColor];
08      
09     //如果是第7个组件,字体颜色设置为蓝色。其余组件设置为红色。
10     if (component == 6) {
11  
12        showLabel.textColor = [UIColor blueColor];
13  
14     }else {
15  
16        showLabel.textColor = [UIColor redColor];
17  
18     }
19  
20     showLable.textAlignment = UITextAlignmentCenter;
21  
22     return [showLabel autorelease];
23 }
24  
25 //这样每次旋转组件时都会创建一个新对象,并放入自动释放池中,如果以后大量旋转,会创建巨量对象。

2 在初始化时,创建模板可变数组,并根据最大组件的总行数,把Label控件插入此可变数组中,再把此模板数组赋值给 dataSource。最后Delegate调用方法返回模板数组中的相应行的对象。

01 //实现第2方案:
02 -(void) viewDidLoad {
03  
04     NSMutableArray * mutableArray = [NSMutableArray arrayWithCapacity:20];
05      
06     for(NSUInteger i = 1;i <= 33 ;i++) {
07  
08         UILabel *showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f,0.0f,20.0f,20.0f)];
09         showLabel.text = [NSString stringWithFormat:@"%d",i];
10         showLabel.backgroundColor = [UIColor clearColor];
11         showLabel.textColor = [UIColor redColor]; //需要显示红色组件多,默认使用红色.
12         showLable.textAlignment = UITextAlignmentCenter;
13         [mutableArray addObject:showLabel];
14         [showLabel release];
15     }//模板初始化完成
16      
17  
18     self.datasourceArray = mutableArray;
19  
20 }
21  
22  
23 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
24  
25     if (component == 6 ) {
26        //如果是第7个组件,返回对象字体颜色设置为蓝色。其余组件设置为红色。
27        UILabel * myLabel = [self.datasource objectAtIndex:row];
28        myLabel.textColor = [UIColor blueColor];
29        return myLabel;
30  
31     }else {
32  
33        return [self.datasource objectAtIndex:row];
34  
35     }
36 }

但是到程序运行时出现问题,正常应该显示7个组件的内容,但现在只能显示一个组件的内容。并且只要旋转其它组件显示出来的内容与已经显示出来的相同,那么已经显示出来的内容就会消失。

例如:程序刚运行时第一个组件显示出了1,2,3.其它组件显示不出内容。如果旋转1组件,显示出4,5,6,7,8,再旋转2组件,当2组件显示出4,5,6,7,8时,1组件的就会消失。

也就是说,不同的组件,如果显示相同的内容时,只会显示最后旋转的组件。

应该是没有把mutableArray数组进行深度复制(Deep Copy)造成,修改原实例变量名为 datasource1,并增加6个新实例变量,datasource2,datasource3 ......datasource7,

再修改viewDidLoad如下:

01 -(void) viewDidLoad {
02  
03     NSMutableArray * mutableArray = [NSMutableArray arrayWithCapacity:20];
04      
05     for(NSUInteger i = 1;i <= 33 ;i++) {
06  
07         UILabel *showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f,0.0f,20.0f,20.0f)];
08         showLabel.text = [NSString stringWithFormat:@"%d",i];
09         showLabel.backgroundColor = [UIColor clearColor];
10         showLabel.textColor = [UIColor redColor]; //需要显示红色组件多,默认使用红色.
11         showLable.textAlignment = UITextAlignmentCenter;
12         [mutableArray addObject:showLabel];
13         [showLabel release];
14     }//模板初始化完成
15      
16     //为每个实例变量deep copy 一份模板数据.
17     for(NSUInteger i = 1;i<=7 ;i++) {
18  
19        NSArray *newArray = [[NSArray alloc] initWithArray:mutableArray copyItems:YES];
20        [self setValue:newArray forKey:[NSString stringWithFormat:@"datasource%d",i]]; //想当于 self.datasource(1-7) = newArray
21        [newArray release];
22     }
23  
24 }

修改delegate方法如下:

01 - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
02  
03     if(component == 0 ) {
04  
05       return [self.datasource1 objectAtIndex:row];
06  
07     }else if (component == 1){
08  
09       return [self.datasource2 objectAtIndex:row];
10  
11     }else if (component == 2){
12  
13       return [self.datasource3 objectAtIndex:row];
14  
15     }else if (component == 3){
16  
17       return [self.datasource4 objectAtIndex:row];
18  
19     }else if (component == 4){
20  
21       return [self.datasource5 objectAtIndex:row];
22  
23     }else if (component == 5){
24  
25       return [self.datasource6 objectAtIndex:row];
26  
27     }else {
28  
29       UILabel * myLabel = [self.datasource7 objectAtIndex:row];
30       myLabel.textColor = [UIColor blueColor];
31       return myLabel;
32  
33     }
34 }

运行程序,这次运行直接退出,打开控制台找到错误提示,原来是因为模板数组中的对象是UILabel,而UILabel没有遵循NSCopying协议,不能进行深度复制。看来第2方案行不通了。

3 创建 UILabel存到Datasource的数组中。delegate直接返回数组中的UILabel。优点是调用委托方法时直接返回相应数据对像即可,缺点是需要先把全部的UILabel创建完成。

//实现第3方案:
-(void) viewDidLoad {
 
    NSMutableArray * mutableArray = [NSMutableArray arrayWithCapacity:20];
    NSUInteger j=0;
    for (NSUInteger i = 1; i <= 7 ;i++) {
 
        j++;
 
        for(NSUInteger i = 1;i <= 33 ;i++) {
 
            UILabel *showLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f,0.0f,20.0f,20.0f)];
            showLabel.text = [NSString stringWithFormat:@"%d",i];
            showLabel.backgroundColor = [UIColor clearColor];
 
            if(j == 7) {
 
                showLabel.textColor = [UIColor blueColor];
 
            }else {
 
                showLabel.textColor = [UIColor redColor];
 
            }
 
            showLable.textAlignment = UITextAlignmentCenter;
            [mutableArray addObject:showLabel];
            [showLabel release];
        }
         
        [self setValue:mutableArray forKey:[NSString stringWithFormat:@"datasource%d",i];
    }
}
 
 
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
 
    if(component == 0 ) {
 
      return [self.datasource1 objectAtIndex:row];
 
    }else if (component == 1){
 
      return [self.datasource2 objectAtIndex:row];
 
    }else if (component == 2){
 
      return [self.datasource3 objectAtIndex:row];
 
    }else if (component == 3){
 
      return [self.datasource4 objectAtIndex:row];
 
    }else if (component == 4){
 
      return [self.datasource5 objectAtIndex:row];
 
    }else if (component == 5){
 
      return [self.datasource6 objectAtIndex:row];
 
    }else {
 
      return [self.datasource7 objectAtIndex:row];
 
    }
}

这次程序运行与第1方案相同,每次旋转组件时,不会创建任何对象。但是在程序初始化时会一次性创建全部所需对像。

总结:

第1方案 动态创建对象,适用于所需对象较多,但旋转较少的情况。(每个组件,每次显示一行,都会调用Delegate方法)。

第3方案 静态创建对象,适用于旋转较多的情况。这样每次调用Delegate方法不会生成任何对象。

多个组件需要使用不同的对象(UILabel).

UILabel不能深度复制.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值