UIPickerView selectedRowInComponent:当我尝试在第二个组件中设置数据时,0总是先返回零

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIPickerView selectedRowInComponent:当我尝试在第二个组件中设置数据时,0总是先返回零相关的知识,希望对你有一定的参考价值。

我是ios编程的新手。

最近,我正在尝试将UIPickerView作为UITextfield中的inputView。

UIPickerView中的数据是关于所有iOS内置字体的。所以我想在UIPickerView中创建两个组件:第一个是familyType,第二个是该familyType中的所有字体。

我模拟来自this answer的代码,但我遇到了一些我无法解决的问题。欢迎任何帮助!

我的问题在这里: 为什么这个函数中的rowOneSelected总是先得到0,即使我提前使用了selectedRowInComponent?

// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if(component == 0)
    {
        return _fontTypeArray.count;
    }
    else
    {
        NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
        FontType *temp = _fontTypeArray[rowOneSelected];
        NSLog(@"%ld", (long)rowOneSelected);    // I use this to debug, and there is a main question: why every time it logs 0 first?
        return temp.font.count;
    }
}

我的所有相关代码都在这里:

在ViewController.h中:

#import <UIKit/UIKit.h>
#import "MenuLayerTwoPlusThree.h"

@interface ViewController : UIViewController

@property MenuLayerTwoPlusThree *layerTwoPlusThree;

- (void)createLayerTwoPlusThree;

@end

在ViewController.m中:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self createLayerTwoPlusThree];
}

- (void)createLayerTwoPlusThree
{
    _layerTwoPlusThree = [MenuLayerTwoPlusThree alloc];

    [_layerTwoPlusThree createFontArray];
    [_layerTwoPlusThree createSelectPanel];
}

在FontType.h中:

#ifndef FontType_h
#define FontType_h

#import <Foundation/Foundation.h>

@interface FontType : NSObject

@property NSString *familyName;
@property NSMutableArray *font;

@end

#endif /* FontType_h */

在FontType.m中:

#import <Foundation/Foundation.h>
#import "FontType.h"

@implementation FontType

@synthesize familyName;
@synthesize font;

@end

在MenuLayerTwoPlusThree.h中:

#ifndef MenuLayerTwoPlusThree_h
#define MenuLayerTwoPlusThree_h

#import <UIKit/UIKit.h>
#import "FontType.h"

@interface MenuLayerTwoPlusThree : NSObject<UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate>

@property UITextField *textFieldFont;    
@property NSMutableArray *fontTypeArray;
@property UIPickerView *pickerFont;
@property UIBarButtonItem *doneButton;
@property UIBarButtonItem *spaceButton;
@property UIBarButtonItem *cancelButton;
@property UIToolbar *toolBar;
@property NSArray *toolBarItems;
@property NSInteger familyType;
@property NSInteger fontType;
@property NSString *fontName;
- (void)createFontArray;
- (IBAction)pickerViewButtonClicked:(id)sender;

@end

在MenuLayerTwoPlusThree.m中

- (void)createFontArray
{
    _fontTypeArray = [[NSMutableArray alloc]initWithCapacity:80];

    int number = 0;

    for(NSString* family in [UIFont familyNames])
    {
        //NSLog(@"%@", family);
        //number++;
        FontType *temp = [[FontType alloc]init];
        temp.familyName = family;
        temp.font = [[NSMutableArray alloc]init];
        int flag = 0;

        for(NSString* name in [UIFont fontNamesForFamilyName:family])
        {
            //NSLog(@" %@", name);
            //number++;
            flag++;
            [temp.font addObject:name];
        }

        // add Heiti SC, Heiti TC, Telugu Sangam MN, and Bangla Sangam MN to font array
        if(flag == 0)
        {
            [temp.font addObject:family];
        }

        [_fontTypeArray addObject:temp];
    }


    // print all fonts test
    for(FontType *x in _fontTypeArray)
    {
        number++;
        NSLog(@"%@", x.familyName);
        for(NSString *y in x.font)
        {
            //number++;
            NSLog(@"	%@", y);
        }
    }      

    NSLog(@"//////////////////////////////");
    NSLog(@"%d", number);
}

- (void)createSelectPanel
{
    [self createSelectPanelForPancel1];
    [self createSelectPanelForPancel2];
    [self createSelectPanelForFont];
    [self createSelectPanelForShape];
    [self createSelectPanelForEraser];
}

- (void)createSelectPanelForFont
{
    _textFieldFont = [[UITextField alloc]initWithFrame:CGRectMake(19, 148, 150, 12)];
    [_textFieldFont setBackground:[UIImage imageNamed:@"font-type-bar.png"]];
    _textFieldFont.rightViewMode = UITextFieldViewModeAlways;
    _textFieldFont.delegate = self;
    [_textFieldFont setPlaceholder:@"Heiti TC"];
    _textFieldFont.font = [_textFieldFont.font fontWithSize:10 * _aspectRatio];


    // resize right view image
    UIImageView *rightViewImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 12 * _aspectRatio, 12 * _aspectRatio)];
    [rightViewImage setImage:[UIImage imageNamed:@"font-type-bar-roll.png"]];
    _textFieldFont.rightView = rightViewImage;


    _pickerFont = [[UIPickerView alloc]init];
    _pickerFont.dataSource = self;
    _pickerFont.delegate = self;
    _pickerFont.showsSelectionIndicator = YES;


    _doneButton = [[UIBarButtonItem alloc]initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(pickerViewButtonClicked:)];
    _spaceButton = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    _cancelButton = [[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(pickerViewButtonClicked:)];
    _toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 45)];
    [_toolBar setBarStyle:UIBarStyleDefault];
    _toolBarItems = [NSArray arrayWithObjects:_cancelButton, _spaceButton, _doneButton, nil];
    [_toolBar setItems:_toolBarItems];

    _textFieldFont.inputView = _pickerFont;
    _textFieldFont.inputAccessoryView = _toolBar;
    if (@available(iOS 9.0, *)) {
        _textFieldFont.inputAssistantItem.leadingBarButtonGroups = @[];
    } else {
        // Fallback on earlier versions
    }
    if (@available(iOS 9.0, *)) {
        _textFieldFont.inputAssistantItem.trailingBarButtonGroups = @[];
    } else {
        // Fallback on earlier versions
    }

    // I want to add these codes to select row in advanced to make sure first time NSLog will print 9, but it doesn't work.
//    [_pickerFont reloadAllComponents];
//    _familyType = 9;
//    _fontType = 0;
//    _fontName = @"Heiti TC";
//    [_pickerFont selectRow:_familyType inComponent:0 animated:YES];

    [_selectPanelFontView addSubview:_textFieldFont];
}

这是委托,我在MenuLayerTwoPlusThree.m中编写:

// The number of columns of data
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if(component == 0)
    {
        return _fontTypeArray.count;
    }
    else
    {
        NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
        FontType *temp = _fontTypeArray[rowOneSelected];
        NSLog(@"%ld", (long)rowOneSelected);    // I use this to debug, and there is a main question: why every time it logs 0 first?
        return temp.font.count;
    }
}

// The data to return for the row and component (column) that's being passed in
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if(component == 0)
    {
        FontType *temp = _fontTypeArray[row];
        return temp.familyName;
    }
    else
    {
        NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
        FontType *temp = _fontTypeArray[rowOneSelected];
        return [temp.font objectAtIndex:row];
    }
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    if(component == 0)
    {
        [_pickerFont reloadComponent:1];
    }

    // This block is moved to pickerViewButtonClicked (sender == _doneButton)
//    else
//    {
//        NSInteger rowOneSelected = [_pickerFont selectedRowInComponent:0];
//        FontType *temp = _fontTypeArray[rowOneSelected];
//        [_textFieldFont setText:temp.font[row]];
//    }
}

- (IBAction)pickerViewButtonClicked:(id)sender
{
    if(sender == _doneButton)
    {
        // Save value when I clicked the done button.
        _familyType = [_pickerFont selectedRowInComponent:0];
        _fontType = [_pickerFont selectedRowInComponent:1];

//        NSLog(@"family: %ld", _familyType);
//        NSLog(@"font: %ld", _fontType);

        FontType *temp = _fontTypeArray[_familyType];
        _fontName = temp.font[_fontType];
        [_textFieldFont setText:_fontName];

//        NSLog(@"font name: %@", _fontName);


        [_textFieldFont endEditing:YES];
    }
    else if(sender == _cancelButton)
    {
        [_textFieldFont endEditing:YES];

        // I want to turn back to the last selected value when I clicked the cancel button.
        [_pickerFont reloadAllComponents];
        [_pickerFont selectRow:_familyType inComponent:0 animated:NO];
        [_pickerFont selectRow:_fontType inComponent:1 animated:NO];
    }
}
答案

看来,当你在组件0中选择了第9行后UIPickerView显示为inputView时,selectedRowInComponent: 0numberOfRowsInComponent: 1中返回0,但随后在titleForRow: row forComponent: 1中返回9。

我不认为你做错了什么,所以它看起来像UIKit中的一个bug。

作为一种解决方法,我建议您不要询问所选行的选择器视图,而是自己跟踪所选行(在视图控制器中初始化您自己的变量并在didSelectRow: row inComponent: 0中更新它)

另一答案

对不起,我忘了发布我的解决方案。

我使用_fontTypeIsFirst来查看是否已选择UIPickerView。当你滚动选择器视图时,你应该将_fontTypeIsFirst设置为NO并重新加载组件1,这样它就像往常一样返回到组件1中的第0行。

这是我的代码:

一些代表:

// The number of columns of data
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

// The number of rows of data
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    if(component == 0)
    {
        return _fontTypeArray.count;
    }
    else
    {
        NSInteger rowOneSelected;
        if (_fontTypeIsFirst == YES)
        {

            rowOneSelected = _selectedRow;
        }
        else
        {
            rowOneSelected = [_pickerFont selectedRowInComponent:0];
        }
        FontType *temp = _fontTypeArray[rowOneSelected];
        return temp.font.count;
    }
}

// The data to return for the row and component (column) that's being passed in
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    if(component == 0)
    {
        FontType *temp = _fontTypeArray[row];
        return temp.familyName;
    }
    else
    {
        NSInteger rowOneSelected;
        if (_fontTypeIsFirst == YES)
        {
            rowOneSelected = _selectedRow;
        }
        else
        {
            rowOneSelected = [_pickerFont selectedRowInComponent:0];
        }

        FontType *temp = _fontTypeArray[rowOneSelected];
        return [temp.font objectAtIndex:row];
    }
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    _fontTypeIsFirst = NO;

    if(component == 0)
    {
        [_pickerFont reloadComponent:1];
    }
}

这是完成和取消按钮的动作:

- (IBAction)pickerViewButtonClicked:(id)sender
{
    if(sender == _doneButton)
    {
        _selectedRow = [_pickerFont selectedRowInComponent:0];
        _familyType = [_pickerFont selectedRowInComponent:0];
        _fontType = [_pickerFont selectedRowInComponent:1];

        FontType *temp = _fontTypeArray[_familyType];
        _fontName = temp.font[_fontType];
        [_textFieldFont setText:_fontName];

        [_textFieldFont endEditing:YES];
        _fontTypeIsFirst = YES;
    }
    else if(sender == _cancelButton)
    {
        [_textFieldFont endEditing:YES];
        _fontTypeIsFirst = YES;

        [_pickerFont selectRow:_familyType inComponent:0 animated:NO];
        [_pickerFont selectRow:_fontType inComponent:1 animated:NO];
    }
}

您可以添加这样的代码来选择viewDidLoad或某个地方的选择器视图的默认值:

_fontTypeIsFirst = YES;
_selectedRow = 9;
_familyType = 9;
_fontType = 0;
_fontName = @"Heiti TC";
[_pickerFont selectRow:_familyType inComponent:0 animated:NO];
[_pickerFont selectRow:_fontType inComponent:1 animated:NO];

以上是关于UIPickerView selectedRowInComponent:当我尝试在第二个组件中设置数据时,0总是先返回零的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIPickerView 是半透明的

如何从另一个 UIPickerview 更改 UIPickerView 的字符串?

UIPickerView 抖动

UIPickerView 选择和隐藏

如果 UIPickerView 未触及,则 UIPickerView 选择第 0 行

点击 uipickerview 时键盘不退出