关于三级联动picker

qq_16876511 2014-06-30 11:29:26
初学xcode,具体要实现的功能为用picker建一个省 / 市 / 邮编,三级联动picker,参照了网络上省市区三级联动自己写了代码,一直未能实现功能,
h文件
#import <UIKit/UIKit.h>
#define PickerOne 0
#define PickerTwo 1
#define PickerThree 2
@interface den : UIViewController<UIPickerViewDataSource,UIPickerViewDelegate>

@property (strong, nonatomic) IBOutlet UIPickerView *pickView;
@property(strong,nonatomic)NSDictionary *zidian;
@property(strong,nonatomic)NSArray *sheng;
@property(strong,nonatomic)NSArray *city;
@property(strong,nonatomic)NSArray *number;
@property(nonatomic,retain)NSArray* selectArray;

- (IBAction)choose:(id)sender;
@end



M文件
#import "den.h"

@interface den ()

@end

@implementation den
@synthesize pickView;
@synthesize zidian;
@synthesize sheng;
@synthesize city;
@synthesize number;
@synthesize selectArray;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{NSBundle *bundle = [NSBundle mainBundle];
//获取code.plist的路径
NSString *listPath = [bundle pathForResource:@"code2" ofType:@"plist"];
//用获取到的路径创建一个字典文件
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:listPath];
//分配给zidian
self.zidian = dictionary;
[dictionary release];

//获取字典里所有的数组
NSArray *components = [self.zidian allKeys];
//按照字母顺序排序
NSArray *sorted = [components sortedArrayUsingSelector:@selector(compare:)];
self.sheng = sorted;
NSString *selectedSheng = [self.sheng objectAtIndex:0];
NSArray *array = [zidian objectForKey:selectedSheng];
//将它分配给zips
self.city = array;
NSArray *components1 = [self.zidian allKeys];
NSArray *sorted1=[components1 sortedArrayUsingSelector:@selector(compare:)];
self.city=sorted1;
NSString *selectedCity=[self.city objectAtIndex:0];
NSArray *array1=[zidian objectForKey:selectedCity];
self.number=array1;
[zidian release];

[super viewDidLoad];
self.pickView.dataSource=self;
self.pickView.delegate=self;
// Do any additional setup after loading the view.
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)choose:(id)sender {
NSInteger shengRow = [pickView selectedRowInComponent:PickerOne];
NSInteger cityRow = [pickView selectedRowInComponent:PickerTwo];
NSInteger zipsRow = [pickView selectedRowInComponent:PickerThree];
//返回选中行的值
NSString *shengName= [self.sheng objectAtIndex:shengRow];
NSString *cityName = [self.city objectAtIndex:cityRow];
NSString *zipsName = [self.number objectAtIndex:zipsRow];
//把选中的值分配给字符串
NSString *title = [[NSString alloc] initWithFormat:@"你选择的邮编是%@",zipsName];
NSString *msg = [[NSString alloc] initWithFormat:@"%@是%@的%@的邮编",
zipsName,shengName,cityName];

UIAlertView *alert=[[UIAlertView alloc]initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[alert release];
[title release];
[msg release];
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 3;
}
//返回给定的组件有多少行数据,我们有2个组件,所以用if操作。后期tableview也是类似的操作方法
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
// switch (component){
// case PickerOne:return [self.sheng count];break;
// case PickerTwo:return [self.city count];break;
// case PickerThree:return [self.number count];break;}


if (component==PickerOne) {
return [self.sheng count];
}
if (component==PickerTwo) {
return [self.city count];
}
if (component==PickerThree) {
return [self.number count];
}
return 0;
}

#pragma mark -
#pragma mark picker 委托方法

//官方的意思是,指定组件中的指定数据,我理解的就是目前选中的是哪一行。
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{

if (component==PickerOne) {
return [self.sheng objectAtIndex:row];
}
if (component==PickerTwo) {
return [self.city objectAtIndex:row];
}
if (component==PickerThree) {
// return [self.number objectAtIndex:row];
}
return nil;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component
{
NSLog(@"row is %d,Component is %d",row,component);
if (component==0) {
self.selectArray=[zidian objectForKey:[self.sheng objectAtIndex:row]];
if ([self.selectArray count]>0) {
self.city= [[self.selectArray objectAtIndex:0] allKeys];
}else{
self.city=nil;
}
if ([self.city count]>0) {
self.number=[[self.selectArray objectAtIndex:0] objectForKey:[self.city objectAtIndex:0]];
}else{
self.number=nil;
}
[pickerView selectedRowInComponent:1];
[pickerView reloadComponent:1];
[pickerView selectedRowInComponent:2];


}
if (component==1) {
if ([selectArray count]>0&&[city count]>0) {
self.number=[[self.selectArray objectAtIndex:0] objectForKey:[self.city objectAtIndex:row]];
}else{
self.number=nil;
}
[pickerView selectRow:0 inComponent:2 animated:YES];

}
[pickerView reloadComponent:2];

}
@end


...全文
448 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
virtualxmars 2014-07-02
  • 打赏
  • 举报
回复
关键是第59行那个方法的实现,如果选中了前两个component,则需要加载下一个component的内容,并手动选中其第一个row,手动选中必须使用第54行的做法,因为只是调用-[UIPickerView selectRow:inComponent:animated:] 只是进行了选中,并不会触发59行didSelect的执行。 上面这种做法是比较简单的,通过代码来产生‘联动’和用户在设备上选中某个component时产生的联动所使用的逻辑是统一的
virtualxmars 2014-07-02
  • 打赏
  • 举报
回复
给你一个比较简单的例子吧:

//
//  ViewController.m
//  PickerDemo
//
//  Created by Charles on 14-7-2.
//  Copyright (c) 2014年 Syncbox. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@end

typedef NS_ENUM(NSInteger, ComponentType) {
    ComponentProvince,
    ComponentCity,
    ComponentMailCode,
};

@implementation ViewController {
    __weak IBOutlet UIPickerView* thePickerView;
    
    NSDictionary* data;
    
    NSArray* provinces;
    NSArray* citys;
    NSArray* mailCodes;
    
    NSString* selectedProvice;
    NSString* selectedCity;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    data = @{
             @"广东": @{
                     @"广州": @[@"510000", @"510001", @"510003"],
                     @"化州": @[@"123456", @"123457", @"123458"],
                     },
             @"湖南": @{
                     @"郴州": @[@"444444", @"444441", @"444445"],
                     @"长沙": @[@"222222", @"222223", @"222224"],
                     }
             };
    
    provinces = [data allKeys];
    [thePickerView reloadAllComponents];

    [self manuallySelectRow:0 inComponent:ComponentProvince];
}

- (void)manuallySelectRow:(NSInteger)row inComponent:(NSInteger)component {
    [thePickerView selectRow:0 inComponent:component animated:YES];
    [self pickerView:thePickerView didSelectRow:0 inComponent:component];
}

- (void)pickerView:(UIPickerView *)pickerView
      didSelectRow:(NSInteger)row
       inComponent:(NSInteger)component
{
    switch (component) {
        case ComponentProvince:
            selectedProvice = provinces[row];
            citys = [data[selectedProvice] allKeys];
            break;
            
        case ComponentCity:
            selectedCity = citys[row];
            mailCodes = data[selectedProvice][selectedCity];
            break;
        
        case ComponentMailCode:
            // 选中邮编时,不需要联动
        default:
            break;
    }

    if (component==ComponentProvince || component==ComponentCity) {
        NSInteger nextComponent = component+1;
        [pickerView reloadComponent:nextComponent];
        [self manuallySelectRow:0 inComponent:nextComponent];
    }
}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 3;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    switch (component) {
        case ComponentProvince:
            return provinces.count;
            
        case ComponentCity:
            return citys.count;
            
        case ComponentMailCode:
            return mailCodes.count;
    }
    
    return 0;
}

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component
{
    switch (component) {
        case ComponentProvince:
            return provinces[row];
            
        case ComponentCity:
            return citys[row];
            
        case ComponentMailCode:
            return mailCodes[row];
    }
    
    return nil;
}

@end
virtualxmars 2014-07-02
  • 打赏
  • 举报
回复
不需要把问题想得很复杂,可简单认为,picker有三个柜子,每个柜子里有可变数量的抽屉。 这些抽屉里显示什么内容完全是你自己指定的。 1. 首先加载所有‘省份’列表,此时,‘市’和‘邮编‘可以是空的。告诉picker进行reload 2. 指定picker默认选中省份中的某一个(例如第一个) 3. picker的delegate会告诉你‘省份’component被选中, 4. 如果‘省份’被选中,则加载对应的‘市’列表,告诉picker reload自己,此时‘邮编’列表是空的。告诉picker进行reload 5. picker的delegate会告诉你‘市’component被选中 6. ‘市’被选中,加载对应的‘邮编’列表,告诉picker进行reload 其实你要做的事情只是替换不同component需要使用的列表内容而已。也就是说,用户选中某个component的某个row时,只要不是邮编component,就改变下一级的component的数据列表源,重新reload,然后用代码选中默认row(例如第一行)
qq_16876511 2014-06-30
  • 打赏
  • 举报
回复
代码一直出错,搞不清三级联动的关系,求知道

29,028

社区成员

发帖
与我相关
我的任务
社区描述
主要讨论与iOS相关的软件和技术
社区管理员
  • iOS
  • 大熊猫侯佩
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧