Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/96.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
UIPicker视图子类不工作IOS_Ios_Uipickerview_Subclassing_Invalidargumentexception - Fatal编程技术网

UIPicker视图子类不工作IOS

UIPicker视图子类不工作IOS,ios,uipickerview,subclassing,invalidargumentexception,Ios,Uipickerview,Subclassing,Invalidargumentexception,作为objective-C编码的新手,我开始编写一个基本的应用程序,完全以编程方式(不使用故事板或xib)在一个文件中,即myAppViewControllerh和m文件。 一切都很顺利 然后我想通过对部分进行子类化来分解大量代码,除了UIPickerView之外,一切都进行得很顺利。事实上,只需注释掉[background addSubview:colorPicker]似乎完全解决了这个问题。我从未在网上找到答案,所以我开始制作一份新的文件来复制上述问题。 下面是: UIPickerViewC

作为objective-C编码的新手,我开始编写一个基本的应用程序,完全以编程方式(不使用故事板或xib)在一个文件中,即my
AppViewController
h和m文件。 一切都很顺利

然后我想通过对部分进行子类化来分解大量代码,除了UIPickerView之外,一切都进行得很顺利。事实上,只需注释掉
[background addSubview:colorPicker]似乎完全解决了这个问题。我从未在网上找到答案,所以我开始制作一份新的文件来复制上述问题。
下面是:

UIPickerViewController.h


设置带有标记的新视图(以便我以后可以用新类引用它) 然后从我的新类中操作一个方法来填充我的新视图

选择器.h


最后是picker类文件中的方法调用的初始化。 这给了我这样一个错误

-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000
2014-03-19 10:29:48.407 Briefcase[1800:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000'

我读到的是与数据源或ARC系统有关的,但是我发现的所有响应都与我上面的设置类型无关或与之相关。我确信这是一件非常简单的事情,但在几天的搜索失败后,这让我发疯。

问题很可能是在
UIPickerViewController
中创建的
Picker
实例从未添加到视图层次结构中,因此过早发布(前提是我们在这里讨论的是使用ARC的项目)

这会导致pickerview的委托和数据源变得无效,并且基本上指向任何随机对象。这就是导致崩溃的原因:无法传递给委托的消息,因为委托已死亡。picker仍保留一个用于指向委托的指针,但该指针已变为无效,并且ts现在在一个随机对象上,在本例中是一个表视图单元格,它基本上不知道如何处理此消息,因此崩溃

如果将Picker*Picker作为ivar或保留/strong属性添加到UIPickerViewController.h,则问题应该会消失-这将保留超出
viewDidLoad
方法范围的Picker,并应使其保持活动状态

但这只是一个解决办法,真正的问题是你的总体设计。你说你是objective-c新手,事实上,看起来你对iOS视图和视图控制器层次结构缺乏基本的了解,在某种程度上,对面向对象编程的概念也缺乏基本的了解。在尝试你的代码是因为,坦率地说,它应该被重新编写而不是修复

我很乐意为您提供有关如何构造代码的建议,但请提供一些关于您希望首先实现哪些功能的信息

编辑(回应您的评论):

  • 根据经验,除非必要,否则不要将功能扩展到多个类。对于用于基础设施用途的对象,如专用文本字段或pickerview,请始终询问自己:“如果我想在另一个项目中重用该对象,这会像使用任何其他现有对象(例如UILabel)一样简单吗?”如果答案是“否”",那么就有问题了。理想情况下,接口对象是自包含的,要使用它们,您只需调用它们,将它们添加到视图中,并告诉它们要显示哪些文本或提供哪些选项。如果该信息可能会更改,或者该对象需要与代码的其他部分交互,请使用委派和协议。在在某些情况下,对象的功能应该绑定到硬编码的值,或者依赖于某个视图来具有特定的标记

  • 如果将UIView子类化,则生成的对象的行为应与UIView的任何其他实例类似。它应由您或某个对象添加到视图层次结构中,但不应添加或删除自身。如果它在未添加到视图层次结构的情况下工作,则会出现问题。视图的目的是作为界面中的一部分,并且它包含的所有逻辑都应该达到这一目的,而不是更多,而不是更少

  • 通常情况下,界面对象不应相互干扰。如果一个对象出现问题(按下按钮,选择选项,更改文本…)另一个对象应该反映这种变化,视图控制器负责实现这种变化。视图控制器是逻辑发生的地方。如果有一个任务需要很多复杂的逻辑,那么最好将该逻辑封装到一个专门构建的类中。一个这样的例子是h管理网络连接。此类应再次自包含:如果视图控制器需要一些远程信息,它会询问您的网络类。一旦您的网络类拥有该信息(或检索失败),它将报告回您的视图控制器。视图控制器然后更新接口-在任何情况下,网络类都不应包含影响接口的代码

重要的是要明白,你完全可以忽略这些规则,最终仍然可以使用一个可用的应用程序。在某些情况下,“直接”这种方法可能看起来更容易实现,因此可能看起来非常诱人。但是,一旦您开始调试代码,您将为此付出代价。如果您的选择器的行为不符合其应有的方式,您需要查看多个位置并围绕多个对象进行思考,以使一个接口对象的行为正确。而且,您可能会破坏o在修复另一个功能的同时,使用新的功能


所以,试着从一开始就做好,尽管这需要更多的计划和学习。相信我,这是值得的,我几年前就和你一样开始了;)

这确实解决了问题!我在UIPickerViewCo中添加了Picker*Picker作为类变量
#import "UIPickerViewController.h"
@interface UIPickerViewController ()
@end

@implementation UIPickerViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    UIView *superview = self.view;
    int height = superview.bounds.size.height;
    int width = superview.bounds.size.width;
    CGRect popupRect = CGRectMake(0, 0, width, height);
    UIView *popup = [[UIView alloc]initWithFrame:popupRect];
    popup.tag = 8;
    [superview addSubview:popup];
    Picker *picker = [[Picker alloc]initWithFrame:popupRect];
    [picker viewAddTypeScreenToView:superview];
}
- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
} 
@end
#import <UIKit/UIKit.h>

@interface Picker : UIView
<UIPickerViewDataSource,UIPickerViewDelegate>
{
    UIPickerView *colorPicker;
    NSMutableArray *colorsArray;
}

@property (nonatomic, retain) UIPickerView *colorPicker;
@property (nonatomic, retain) NSMutableArray *colorsArray;
@property (strong,nonatomic) UILabel *myValue;

-(void)viewAddTypeScreenToView:(UIView*)superview;

@end
#import "Picker.h"

@implementation Picker

@synthesize colorsArray;
@synthesize colorPicker;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
    }
    return self;
}


-(void)viewAddTypeScreenToView:(UIView*)superview
{
    UIView *baseView =[superview viewWithTag:8];

    int height = baseView.bounds.size.height;
    int width = baseView.bounds.size.width;

    CGRect fullScreen = CGRectMake(0, 0, width, height);
    UIView *background = [[UIView alloc]initWithFrame:fullScreen];
    background.backgroundColor = [UIColor blackColor];

    colorsArray = [[NSMutableArray alloc] initWithObjects:@"Red",@"Blue",@"Yellow",@"Green",nil];

    CGRect myPickerRect = CGRectMake(10, 70, (width/2)-40, 200);
    colorPicker = [[UIPickerView alloc]initWithFrame:myPickerRect];
    colorPicker.dataSource = self;
    colorPicker.delegate = self;
    colorPicker.showsSelectionIndicator = YES;
    [colorPicker selectRow:2 inComponent:0 animated:YES];

    CGRect labelFrame = CGRectMake(10, 10, 180, 50);
    _myValue = [[UILabel alloc]initWithFrame:labelFrame];
    _myValue.textColor = [UIColor redColor];
    _myValue.text = @"select colour";
    [background addSubview:_myValue];
    [background addSubview:colorPicker];
    [baseView addSubview:background];

}



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

-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
    return colorsArray.count;;
}

-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return colorsArray[row];
}

-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
    _myValue.text = [NSString stringWithString:colorsArray[row]];
}

@end
-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000
2014-03-19 10:29:48.407 Briefcase[1800:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCellContentView pickerView:titleForRow:forComponent:]: unrecognized selector sent to instance 0x8f2b000'