SIGABRT在任何UIView触摸上
恐怕没有任何数量的谷歌搜索已经能够保存我的海德了。我在任何时候在任何UIView上触摸手机的屏幕时,似乎都会收到SIGABRT错误。调试器控制台的帖子这个错误的SIGABRT前:SIGABRT在任何UIView触摸上
.... [310:207] *** -[UIView _exclusiveTouchView]: unrecognized selector sent to instance 0x14c0c0
.... [310:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[UIView _exclusiveTouchView]: unrecognized selector sent to instance 0x14c0c0'
(这不是我要_exclusiveTouchView
特定的呼叫,当然)。
我会很高兴地发布一些代码,但事实是我无法找到(或猜测)这个问题可能来自哪里。这不会发生在任何一个UIView上,而是在我的堆栈中的所有UIViews上。不过,我可以总结一下显示逻辑,也许这样会显露出一些亮点。
所以创建应用程序并分配UIWindow。然后分配一个单独的viewcontroller,这会创建并添加自己的空白self.view,其中附加了代表不同游戏状态的其他UIViews。
有趣的是,这个错误不会发生在模拟器上,但会一直发生在设备上。我还应该提到应用程序尚未覆盖/使用任何touchesBegan:/ Ended:/ Moved:等等......换言之,在代码中发生这种错误而没有这些方法。
我真的不知道这个错误来自哪里......任何建议?
EDIT这里请求码是仍然生成触摸SIGABRT的简化状态:
#import <UIKit/UIKit.h>
#import "WPGame.h"
@class WPGame;
extern WPGame *theGame;
#import "WPGameState.h"
@class IntroView;
@interface IntroStateView : WPGameState {
NSTimer *introTimer;
}
+(IntroStateView*)instance;
@end
。
#import "IntroStateView.h"
#import "StartMenuStateView.h"
static IntroStateView *theOnlyIntro = nil;
@implementation IntroStateView
+(IntroStateView*)instance {
@synchronized(self) {
if (!theOnlyIntro) {
theOnlyIntro = [[IntroStateView alloc] init];
}
}
return theOnlyIntro;
}
- (void)excuseYourself {
[self changeStateOf:theGame toState:[StartMenuStateView instance]];
}
- (void)startUp {
[super startUp];
introTimer = [NSTimer scheduledTimerWithTimeInterval:[theGame introLength]
target:self
selector:@selector(excuseYourself)
userInfo:NULL
repeats:NO];
}
- (void)cleanUp {
[super cleanUp];
}
- (void)handleEvents:(WPGame*)game {
[super handleEvents:game];
}
- (void)dealloc {
theOnlyIntro = nil;
[super dealloc];
}
@end
,如果你需要看到的UIView的WPGameState子类的部分,它可以在这里找到了节省一些后长度:http://tinypaste.com/732bb
好的,问题解决了 - 似乎主应用程序的单例window
变量与游戏状态管理器使用window
变量之间有一些名称冲突。正如TechZen提到的那样,代码试图将UIWindow消息发送到没有方法的UIView。这里,window
由主应用程序作为一个UIWindow和window
单独使用也正在被WPGameState作为其视口,一个UIView,框架内引起歧义。
二使用的window
已更名为viewport
,解决问题。
的第一个想法:_exclusiveTouchView是一个UIWindow的成员变量,它出现该设备的视图层次结构中没有UIWindow,更具体地说,它的响应者链。确保窗口确实正在分配,并且是视图层次结构的顶层视图。您是使用Interface Builder还是自己动手制作?
滚动我自己的。应用程序委托装载负责接管整个应用程序的单例类。这是其中一个UIWindow被声明和alloc'd下列方式(窗口是具有保留属性的类变量): 窗口= [[ALLOC的UIWindow] initWithFrame:方法[[UIScreen mainScreen]界限]]; [window makeKeyAndVisible]; 从此,视图控制器被加载,使其自身的self.view并将THAT附加到[window addSubview :(单个VC self.view)] – bitcruncher 2010-04-23 16:20:15
UIView \t * window;建立?你可以请张贴你的启动代码吗?这通常是在东西 - (空)的applicationDidFinishLaunching:(UIApplication的*)应用程序... 什么是viewOutlet初始化? window = [theGame viewOutlet]; ---提示----- 在你的初始化代码,你调用[超级初始化],然后..initWithFrame(也叫[超级初始化。这是不好的,只是子类(ID)initWithFrame :(CGRect)aRect或不明确地调用[super init] – gnasher 2010-04-23 16:45:10
UIWindow *窗口在游戏单例标题中被声明为一个类变量,它被分配在单例实现文件中,如我上面的注释中所述。 (+1) – bitcruncher 2010-04-23 22:13:32
我认为问题在于你将某个视图分配给应该保存一个窗口的属性。该代码试图发送一个UIWindow消息到没有该方法的UIView。 (UIWindow是UIView的子类。)
我没有看到直接的原因,但是他的应用程序显示出严重的设计问题。你有一个WPGameState的UIView子类,它本身有一个名为window
的UIView属性。这严重打破了模型 - 视图 - 控制器的设计模式。
WPGameState
和IntroStateView
都不属于视图,该逻辑属于视图控制器。你应该有一个单一的视图控制器来管理这两个视图并处理它们的显示,定时器等。视图应该只知道如何绘制自己以响应来自视图控制器的命令。
(以及为什么explicative缺失是有单看法呢?这是一种单滥用行为得到禁止使用在一些商店单身。)
也不应该将“游戏状态”是在任何一个视图或视图控制器而是应当驻留在其自己的自定义数据模型对象。
那种你看到的问题是,为什么MVC是首先使用。通过在视图中填充如此多的逻辑,只需触摸界面即可引发不可预知的级联错误。如果您的设计更加模块化并且功能明确分离,则您可以自动知道问题来自何处。
@TechZen - 好的,我看到你来自哪里,虽然我不同意。在这里,我有一个视图控制器运行为显示服务器,而通过单例实现的视图(个人和独特的游戏状态),根据需要附加到显示服务器的self.view,这就是为什么该类不包含关键逻辑,除了设备旋转和ge neralized视图管理。在这家商店里,我们尊重MVC方法的某些任务,但这不是其中之一。然而,我会很乐意在这里提出你的答案,因为它确实帮助我找到了实际的错误。 – bitcruncher 2010-04-23 18:18:56
我不会告诉您您的业务,但我会建议您将您的设计与API匹配。我可以从你的术语中知道你来自一个强大的C++(或类似的)背景,并且你试图将这种体验映射到这个API上。 Objective-C和API足够灵活,你可以做任何你想做的事情,但是如果你不围绕一个强大的MVC设计构建,你将会一直与API战斗,而不是让它帮助你。 – TechZen 2010-04-24 13:11:08
请提供重现问题的最简单的UIView子类代码。我们将能够从那里提供帮助。 – 2010-04-23 15:24:02
不知道它是否直接相关,但使用单身视图绝对是单身滥用。意见应该是愚蠢和可互换的。每个视图应该只有足够的逻辑来处理其即时显示需求。他们不应该有关键的应用程序逻辑,以便每个应用程序只有一个存在。你需要重新考虑你的设计。 – TechZen 2010-04-23 16:32:59
@TechZen - 在设计方面,这些独特的视图负责代表各个游戏状态的大部分自己的环境。他们意味着有重要的逻辑,但不是应用逻辑。不过,我同意非游戏应用程序应该远离单例视图。 – bitcruncher 2010-04-23 17:45:03