iPhone:IBAction导致“Unrecognized Selector Sent to Instance”错误

3
我是你的助手,接下来为你翻译内容。
我正在开发我的第一个真正的iPhone应用程序,一个简单的待办事项列表应用程序,帮助我组织事情,但我遇到了“未识别的选择器发送到实例0x”的问题。
具体来说:
2010-02-20 14:30:09.200 ToDoApp[88562:20b] *** -[NSCFDictionary switchViews:]: unrecognized selector sent to instance 0x3d22de0

2010-02-20 14:30:09.201 ToDoApp[88562:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary switchViews:]: unrecognized selector sent to instance 0x3d22de0'

我已经查看了相关内容,发现可能是IB中的连接问题,但我对连接这个整个过程还很陌生(天哪,我希望他们支持Java或Python),以下是它的布局方式。我有3个类,一个SwitchViewController、一个MainScreenViewController和一个ToDoListViewController。当我在MainScreenViewController上点击一个按钮时,就会触发“switchViews”函数,而这个函数就出现了问题。我设置的方式是,这个按钮(一个UIBarButtonItem)的“sentAction”指向switchViews。这个ViewButton将其引用输出作为SwitchViewController中的IBOutlet。
以下是SVC的.h文件:
#import <UIKit/UIKit.h>

@class MainScreenViewController;
@class ToDoListViewController;
@class EditViewController;

#define kMinimumGestureLength 25
#define kMaximumVariance 5

@interface SwitchViewController : UIViewController {
 MainScreenViewController *mainScreenViewController;
 ToDoListViewController *toDoListViewController;
 EditViewController *editViewController;
 IBOutlet UIBarButtonItem *viewButton;
 CGPoint gestureStartPoint;
}

@property (retain, nonatomic) MainScreenViewController *mainScreenViewController;
@property (retain, nonatomic) ToDoListViewController *toDoListViewController;
@property (retain, nonatomic) EditViewController *editViewController;
@property (retain, nonatomic) IBOutlet UIBarButtonItem *viewButton;
@property CGPoint gestureStartPoint;
-(IBAction)switchViews:(id)sender;  

对于switchViews函数:

-(IBAction) switchViews:(id)sender
{
 NSLog(@"Switching views");
 if(self.toDoListViewController.view.superview == nil){
  if(self.toDoListViewController ==nil){
   ToDoListViewController *toDoVC = [[ToDoListViewController alloc]     initWithNibName:@"ToDoListView" bundle:nil];
   self.toDoListViewController = toDoVC;
   //[toDoVC release];
  }
  [mainScreenViewController.view removeFromSuperview];
  [self.view insertSubview:toDoListViewController.view atIndex:0];
 }
 else{
  if(self.mainScreenViewController == nil){
   MainScreenViewController *mainController =     [[MainScreenViewController alloc] initWithNibName:@"MainScreenView" bundle:nil];
   self.mainScreenViewController = mainController;
   //[mainController release];
  }
  [toDoListViewController.view removeFromSuperview];
  [self.view insertSubview:mainScreenViewController.view atIndex:0];
 }
}

简而言之,我完全迷失了方向,这真的很令人沮丧。有人有任何建议或需要更多代码吗?

7个回答

12
我们遇到了相同的问题。看起来我们在AppDelegate中释放了ViewController对象,然后我们的nib视图试图调用一个IBAction(来自ViewController)。有一半的时间我们得到"EXC_BAD_ACCESS"(也就是向已释放的对象发送消息),另一半的时间我们得到NSCFString、NSCFArray等各种东西的"unrecognized selector sent to instance"(也就是向现在由不同对象占据的内存区域发送消息)。
请确保您的ViewController没有被释放。

我来这里报告正是这个问题。我遇到了各种对象的奇怪的访问错误崩溃。这是我首先想到的可能是内存问题。最初,我以为我忘记设置正确的文件所有者了。实际上,我在viewDidLoad方法中意外地实例化了一个视图控制器,在调用IBAction时它已经为空了! - anders

4

好的,有人给我指出了解决方案。 应该通过FirstResponder路由(我真的不明白为什么它可以工作,但此时此刻我只是高兴它可以工作)。

我不确定FirstResponder到底是如何工作的(我拥有的所有书籍都没有提到它),但它确实可以工作?如果有人想给我一个简要介绍,那会很有用...但这个问题已经得到了解答。


在编程中,遇到完全相同的问题,之后通过FirstResponder路由解决了(但仍不知道为什么这有效)。 - jbnunn

0
问题在于,您已将UIViewController实例作为方法变量初始化。因此,在方法执行后,视图控制器没有范围,因此它从内存循环中释放。因此,您必须将视图控制器实例设置为类级别。
  @interface SwitchViewController () {
         ToDoListViewController *toDoVC;
         MainScreenViewController *mainController;
    }



-(IBAction) switchViews:(id)sender
{
     if (!toDoVC)
          toDoVC = [[ToDoListViewController alloc]     initWithNibName:@"ToDoListView" bundle:nil];
     if (!mainController)
          mainController =     [[MainScreenViewController alloc] initWithNibName:@"MainScreenView" bundle:nil];

 //Your stuff with the view controllers...
}

0
正确的答案是:
我们在应用程序委托中分配为第一个屏幕的视图控制器不应该在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中释放。 在您的情况下,第一个屏幕是MainScreenViewControllerMainScreenViewController实例应该在应用程序委托的dealloc方法中释放。
- (void)dealloc
{
    [_window release];
    [mainScreenViewController release];
    [super dealloc];
}

0

这可能也会有所帮助。分析程序建议我释放一些对象,我也按照建议做了。结果发现,我在应用程序中确实需要这些对象。在xAppDelegate.m文件(或任何其他文件)的appDidFinishLaunching方法/消息/函数/例程/东西中使用:

UINavigationController *navController = [[UINavigationController alloc] init];

替代

UINavigationController *navController = [[[UINavigationController alloc] init] autorelease];

此外,分析器建议我释放我推到导航控制器上的对象。这是一个大错误。那个文件是我的菜单屏幕,当我按下一个按钮时,我收到了“未识别的选择器发送到实例”的错误。显然,它正在调用NSString和NSDictionary上的IBAction,这是不好的。

0

我猜问题出在你的nib文件中。

这个错误意味着,当点击按钮时,按钮会尝试向一个NSDictionary对象发送一个名为switchView的消息/方法调用,而这个对象显然没有这样的方法。因此,错误在于按钮的操作指向何处。

检查这个视图的nib文件。查看文件所有者并检查分配给它的类。确保它是SwitchViewController而不是某个字典。如果文件所有者属性设置为字典类,它将加载一个字典并尝试将操作方法发送到它。


它所分配的类是“MainScreenViewController”,这更或多或少是一个空的视图控制器类,旨在在其中一个按钮被点击时做出反应。我在IB中将SwitchViewController作为MainScreenView的外部对象,并将IBOutlet viewButton连接到MainScreenView中的UIBBI(它被视为SwitchViewController视图的子视图)。如果有帮助的话。 - Althane
这是正确答案吗?如果是,您需要勾选它。否则系统将记录此问题未回答。 - TechZen

0

顺便提一下,当我使用ARC并且xib被加载并放置到屏幕上时,我遇到了这个问题,但是某种方式下VC本身没有被保留。

我通过添加一个变量来存储呈现它的VC的引用来解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接