无法根据 UIPickerview 中第一个组件中的值重新加载第二个组件

Posted

技术标签:

【中文标题】无法根据 UIPickerview 中第一个组件中的值重新加载第二个组件【英文标题】:Not able to reload second compoenent based on value in first component in UIPickerview 【发布时间】:2014-03-24 20:18:46 【问题描述】:

我正在使用 UIPickerView 并尝试使用映射到第一个组件中选择的值的数据来实现加载第二个组件的功能。但是,我的第二个组件始终显示映射到我的第一个组件的第二行的值。

通过断点,我注意到 - (UIView *)pickerView:(UIPickerView *)iPickerView viewForRow:(NSInteger)iRow forComponent:(NSInteger)iComponent reusingView:(UIView *)iView 方法的值被正确传递。

请看看我到目前为止做了什么。我错过了什么吗?

#import "ViewController.h"
#import "ZXingObjC.h"

@interface ViewController ()

@property (nonatomic, assign) IBOutlet UITextField *barcodeTextField;
@property (nonatomic, assign) IBOutlet UIImageView *barcodeImageView;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollview;
@property (nonatomic, strong) NSArray *barcodeTypes;
@property (nonatomic, strong) NSDictionary *barcodes;
@property (nonatomic, assign) NSInteger selectedBarcodeType;

@end


typedef enum 
    OneDBarcode = 0,
    TwoDBarcode
 BarcodeTypes;


@implementation ViewController

- (void)loadView 
    [super loadView];

    UITapGestureRecognizer *aTapInsideTableView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    [aTapInsideTableView setCancelsTouchesInView:NO];
    [self.view addGestureRecognizer:aTapInsideTableView];



- (void)viewDidLoad 
    [super viewDidLoad];

    NSArray *twoDBarcodes = @[@"Aztec", @"DataMatrix", @"MaxiCode", @"PDF417", @"QRCode", @"RSS14", @"RSSExpanded"];
    NSArray *oneDBarcodes = @[@"Codabar", @"Code39", @"Code93", @"Code128", @"Ean8", @"Ean13", @"ITF", @"UPCA", @"UPCE", @"UPCEANExtension"];
    self.barcodes = @@"1D Barcodes": oneDBarcodes, @"2D Barcodes": twoDBarcodes;

    self.barcodeTypes = @[@"Aztec", @"Codabar", @"Code39", @"Code93", @"Code128", @"DataMatrix", @"Ean8", @"Ean13", @"ITF", @"MaxiCode", @"PDF417", @"QRCode", @"RSS14", @"RSSExpanded", @"UPCA", @"UPCE", @"UPCE"];

    self.selectedBarcodeType = OneDBarcode;

    [self.scrollview setScrollEnabled:YES];
    [self.scrollview setContentSize:CGSizeMake(320.0, 750.0)];



- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.



- (IBAction)generateBarcode:(id)sender 
    UIImage *barcodeImage = [self barcodeImageForText:self.barcodeTextField.text];
    if (barcodeImage) 
        self.barcodeImageView.image = barcodeImage;
    



- (IBAction)dismissView:(id)iSender 
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];



- (UIImage *)barcodeImageForText:(NSString *)iBarcode 
    NSError* error = nil;
    ZXMultiFormatWriter* writer = [ZXMultiFormatWriter writer];
    ZXBitMatrix* result = [writer encode:iBarcode
                                  format:kBarcodeFormatQRCode
                                   width:500
                                  height:500
                                   error:&error];
    if (result) 
        CGImageRef image = [[ZXImage imageWithMatrix:result] cgimage];

        // This CGImageRef image can be placed in a UIImage, NSImage, or written to a file.

        return [UIImage imageWithCGImage:image];
     else 
        NSString* errorMessage = [error localizedDescription];
        NSLog(@"Error: %@", errorMessage);
        return nil;
    



- (void)handleTap:(UITapGestureRecognizer *)iRecognizer 
    if (self.barcodeTextField) 
        [self.barcodeTextField resignFirstResponder];
    



#pragma mark - UIPickerViewDataSource methods

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)iPickerView 
    return self.barcodes.allKeys.count;



- (NSInteger)pickerView:(UIPickerView *)iPickerView numberOfRowsInComponent:(NSInteger)iComponent 
    NSArray *barcodeKeys = self.barcodes.allKeys;
    NSArray *barcodeValues = self.barcodes[barcodeKeys[iComponent]];

    if (iComponent == OneDBarcode) 
        return barcodeKeys.count;
    

    return barcodeValues.count;



#pragma mark - UIPickerViewDelegate methods

- (UIView *)pickerView:(UIPickerView *)iPickerView viewForRow:(NSInteger)iRow forComponent:(NSInteger)iComponent reusingView:(UIView *)iView 
    UILabel *label = (UILabel *)iView;

    if (!label) 
        label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 60.0f)];
        label.backgroundColor = [UIColor clearColor];
        label.textAlignment = NSTextAlignmentCenter;
        label.adjustsFontSizeToFitWidth = YES;
    

    NSArray *barcodeKeys = self.barcodes.allKeys;
    NSArray *barcodeValues = self.barcodes[barcodeKeys[iComponent]];

    NSString *labelText;

    if (iComponent == OneDBarcode) 
        labelText = barcodeKeys[iRow];
     else if (iComponent == TwoDBarcode) 
        labelText = barcodeValues[iRow];
    

    label.text = labelText;

    return label;



- (void)pickerView:(UIPickerView *)iPickerView didSelectRow:(NSInteger)iRow inComponent:(NSInteger)iComponent 
    [iPickerView reloadComponent:iComponent];

    if (iComponent == OneDBarcode) 
        self.selectedBarcodeType = OneDBarcode;
     else 
        self.selectedBarcodeType = TwoDBarcode;
    

    [iPickerView reloadAllComponents];


@end

【问题讨论】:

【参考方案1】:

代码有很多地方有问题。当用户在选择器中选择一行时,如果用户在第一个中选择了值,则仅加载第二个组件。在任何情况下都不要重新加载。

viewForRow方法中,你有两个问题:

    字典没有顺序,并且获取键没有顺序。但是数组中第一个组件的值,因此您可以通过索引访问它们。 您尝试访问barcodeValues 是基于该组件。它应该基于第一个组件的选定索引。

【讨论】:

知道了。修复了数据结构,现在可以正常工作了。

以上是关于无法根据 UIPickerview 中第一个组件中的值重新加载第二个组件的主要内容,如果未能解决你的问题,请参考以下文章

无法根据选择从 UIPickerView 中删除项目

UIPickerView - 无法在 ios7 中点击要选择的项目

如何获取 UIPickerView 中组件的位置?

无法根据来自 UIPickerView 的选择器更新 UITableView 数据

关于多组件依赖uipickerview的实现

当组件 0 更改时,重置 UIPickerView 的第一个组件的值