Ios 为什么其他调用方法的东西通过接口生成器xib连接到UIBarButtonItem?
按下RightBarButtonim自定义视图中的按钮时,我的iOS应用程序崩溃。使用自定义视图是因为barButtonItem设计需要的不仅仅是按钮 以下是崩溃的输出:Ios 为什么其他调用方法的东西通过接口生成器xib连接到UIBarButtonItem?,ios,interface-builder,uibarbuttonitem,objective-c-category,unrecognized-selector,Ios,Interface Builder,Uibarbuttonitem,Objective C Category,Unrecognized Selector,按下RightBarButtonim自定义视图中的按钮时,我的iOS应用程序崩溃。使用自定义视图是因为barButtonItem设计需要的不仅仅是按钮 以下是崩溃的输出: [UIViewControllerWrapperView buttonPressed:]: unrecognized selector sent to instance 0x7669430] *** Terminating app due to uncaught exception 'NSInvalidArgumentExce
[UIViewControllerWrapperView buttonPressed:]: unrecognized selector sent to instance 0x7669430]
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewControllerWrapperView buttonPressed:]: unrecognized selector sent to instance 0x7669430'
自定义视图在单独的视图控制器的xib RightBarButtonie MVC中定义,该视图还包含以下链接方法:
- (IBAction)buttonPressed:(id)sender {
NSLog(@"button pressed");
}
viewDidLoad中使用RightBarButtonItem MVC,用于所有需要该项的视图控制器:
- (void)viewDidLoad
{
[super viewDidLoad];
RightBarButtonItemVC *rightBarButtonItemVC = [[RightBarButtonItemVC alloc] initWithNibName:@"RightBarButtonItemVC" bundle:nil];
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightBarButtonItemVC.view];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
}
请注意,我是如何将rightBarButtonItem的视图指定为rightBarButtonItem的视图的
问题:
UIViewControllerRapperView
没有调用您的选择器;您的按钮正在调用UIViewControllerRapperView
上的-按钮按下:
。试试看
看起来您使用的是rightbarbuttoniemvc
,只是作为一个视图加载程序(我假设您使用的是ARC,否则它会泄漏)。这是昂贵的,除非在其他地方使用视图之前设置rightbarbuttoniemvc.view=nil
,否则可能会发生奇怪的事情(我完全忘了是什么)。我提出了一种从NIB加载视图的更好方法(我不知道Interface Builder是否支持协议拥有的NIB,这将是理想的)
代码崩溃的主要原因有两个:
- 在NIB中,
连接到错误的对象。我认为这不太可能-按钮按下:
将被发送到-按钮按下:
,但右按钮MVC
不被任何东西保留,因此被解除分配。它被发送到在同一地址分配的下一个对象,该对象恰好是右按钮MVC
UIViewControllerRapperView
- 删除Interface Builder中的连接,并使用以编程方式添加它。这需要在视图层次结构中查找按钮
- 首先以编程方式创建它
@interface UIViewController (BarButtonItemLoader)
在UIViewController+BarbuttonimLoader.h中,定义此方法:
- (UIBarButtonItem *) rightBarButtonItem;
由于无法跟踪类别中的状态,请在AppDelegate.h中定义UIBarButtonItem:
@property (strong, nonatomic) UIBarButtonItem *rightBarButtonItem;
接下来,通过从AppDelegate延迟加载RightBarButtonim(不要忘记导入“AppDelegate.h”),开始实现类别的RightBarButtonim方法。这将确保在AppDelegate中只创建并保留一个RightBarButtonim:
- (UIBarButtonItem *) rightBarButtonItem {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(!appDelegate.rightBarButtonItem) {
//create a rightBarButtonItem (see below)
}
return appDelegate.rightBarButtonItem;
}
开始组装将设置为RightBarButtonim的UIView/UIBarButtonim。从旧的Interface Builder/xib实现中传输每个元素/配置。最重要的是,请注意Size inspector中的框架信息,以便您可以通过编程方式定位子视图,就像您在.xib文件中手动定位子视图一样
- (UIBarButtonItem *) rightBarButtonItem {
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(!appDelegate.rightBarButtonItem) {
UIView *rightBarView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 264, 44)];
UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightBarView];
UIImageView *textHeader = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"textHeader.png"]];
textHeader.frame = CGRectMake(2, 14, 114, 20);
[rightBarView addSubview:textHeader];
UIButton *button1 = [[UIButton alloc] initWithFrame:CGRectMake(100, 2, 70, 44)];
[button1 setImage:[UIImage imageNamed:@"button1.png"] forState:UIControlStateNormal];
[button1 setImage:[UIImage imageNamed:@"button1Highlighted.png"] forState:UIControlStateHighlighted];
[button1 addTarget:self action:@selector(button1Pressed) forControlEvents:UIControlEventTouchUpInside];
[rightBarView addSubview:button1];
UIButton *button2 = [[UIButton alloc] initWithFrame:CGRectMake(194, 2, 70, 44)];
[button2 setImage:[UIImage imageNamed:@"button2.png"] forState:UIControlStateNormal];
[button2 setImage:[UIImage imageNamed:@"button2Highlighted.png"] forState:UIControlStateHighlighted];
[button2 addTarget:self action:@selector(button2Pressed) forControlEvents:UIControlEventTouchUpInside];
[rightBarView addSubview:button2];
appDelegate.rightBarButtonItem = rightBarButtonItem;
}
return appDelegate.rightBarButtonItem;
}
最后,实现UIViewController+barbuttonimloader.m中的buttonXPressed方法,以达到您的目的:
- (void) button1Pressed {
NSLog(@"button1 Pressed");
}
- (void) button2Pressed {
NSLog(@"button2 Pressed");
}
通过将此代码添加到任何UIViewController或其子类来使用类别:
#import "UIViewController+BarButtonItemLoader.h"
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = [self rightBarButtonItem];
}
总结
这种方法允许您动态地向任何UIViewController添加UIBarButtonItem。缺点是必须将上述代码添加到所创建的所有UIViewController中
另一种选择
如果希望进一步封装UIBarButtonims(或其他任何内容)的添加,避免在每个视图控制器中添加代码,则应创建BaseViewController,然后从中对所有其他视图控制器进行子类化。从那里,您可以考虑要包含在所有视图控制器中的其他项。选择类别或子类路由将成为粒度问题。我认为您不能像那样“共享”视图控制器的视图。为什么不在xib中创建一个视图而不是视图控制器?我考虑过了,但是如果我这样做了,我必须在每个视图控制器中定义目标方法,对吗?为什么?你放在按钮上的图像与其目标方法有什么关系?我不确定你的意思,因为我正在加载一个带有自定义视图的uibarbuttonite,而不仅仅是将图像应用于按钮。有什么方法可以让这个问题变得更好?我对downvoteTY很好奇——我不会说RightBarButtonItemVC只是一个视图加载器——它应该响应按钮的按下并采取适当的措施。如果我只做一个xib,那么我就失去了将所有按钮响应保持在一个位置的能力。如果我正确理解了您的方法,这意味着我需要在viewDidLoad中为每个想要使用UIBarButtonim的新视图控制器添加目标。我希望如果你有一个解决方案,包括这一点,就可以避免这种情况。@kraftydevil那么要么需要保留正确的MVC,要么希望此功能的VCs需要子类