问题
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
回答1:
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:
- 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.
- Your attempt to access
barcodeValues
is based on the component. It should be based on the selected index of the 1st component.
来源:https://stackoverflow.com/questions/22619754/not-able-to-reload-second-compoenent-based-on-value-in-first-component-in-uipick