Domanda

I am working with a UIPickerView and trying to implement the functionality of loading second component with the data that is mapped to value selected in the first component. But, my second component always shows the values that are mapped to second row of my first component.

With breakpoints I noticed the values are correctly passed on for - (UIView *)pickerView:(UIPickerView *)iPickerView viewForRow:(NSInteger)iRow forComponent:(NSInteger)iComponent reusingView:(UIView *)iView method.

Please see what I have done by far. Am I missing something?

#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
È stato utile?

Soluzione

There are many thins wrong with the code. When the user picks a row in the picker, only load the 2nd component if the user chose value in the 1st. Don't reload all under any case.

In the viewForRow method, you have two problems:

  1. Dictionaries are not ordered and get the keys has no order. But the values for the 1st component in an array so you can access them by index.
  2. Your attempt to access barcodeValues is based on the component. It should be based on the selected index of the 1st component.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top