0

残念ながら、Google をいくら検索しても、これで私のハイドを救うことはできませんでした。どのUIViewでも、電話の画面に触れるたびにSIGABRTエラーが発生しているようです。デバッガー コンソールは、SIGABRT の前に次のエラーをポストします。

.... [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。)

喜んでコードを投稿しますが、実際には、この問題がどこから発生しているのかを見つける (または推測する) ことはできません。これは、1 つの UIView では発生していませんが、スタック内のすべての UIView で発生しています。ただし、表示ロジックを要約することはできますが、おそらくそれでいくらかの光が当たるでしょう。

したがって、アプリケーションが作成され、UIWindow が割り当てられます。次に、単一のビューコントローラーが割り当てられ、それが独自の空白の self.view を作成して追加します。これには、さまざまなゲームの状態を表す他の UIView がアタッチされます。

興味深いことに、このエラーはシミュレーターでは発生しませんが、デバイスでは一貫して発生します。また、アプリケーションがまだ 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

4

3 に答える 3

1

問題は、ウィンドウを保持する必要があるプロパティにビューを割り当てていることだと思います。コードは、メソッドを持たない UIView に UIWindow メッセージを送信しようとしています。(UIWindow は UIView のサブクラスです。)

直接の原因はわかりませんが、このアプリには深刻な設計上の問題があります。という UIView プロパティを持つ WPGameState の UIView サブクラスがありますwindow。これは、Model-View-Controller デザイン パターンをひどく壊します。

どちらのロジックもビューに属しておらず、そのロジックはView Controllerに属していますWPGameStateIntroStateView両方のビューを管理し、それらの表示、タイマーなどを処理する単一のビュー コントローラーが必要です。ビューは、ビュー コントローラーからのコマンドに応答して自分自身を描画する方法のみを知っている必要があります。

(そして、なぜ説明削除されたシングルトンビューがあるのでしょうか? これは、一部のショップでシングルトンの使用が禁止されるようなシングルトンの悪用です。)

「ゲームの状態」は、ビューまたはビュー コントローラーのいずれかにあるべきではなく、代わりに独自のカスタム データ モデル オブジェクトに存在する必要があります。

あなたが見ている種類の問題は、そもそもなぜ MVC が使用されているかということです。ビューに非常に多くのロジックを詰め込むことで、インターフェイスに触れるだけで、予測できない一連のエラーを引き起こすことができます。設計がモジュール化され、機能が明確に分離されていれば、この問題の原因が自動的にわかります。

于 2010-04-23T16:47:05.810 に答える
0

最初の考え:_exclusiveTouchViewはUIWindowのメンバー変数であり、デバイスのビュー階層、より具体的にはレスポンダーチェーンにUIWindowがないようです。ウィンドウが実際に割り当てられており、ビュー階層の最上位のビューであることを確認してください。Interface Builderを使用していますか、それとも独自のローリングを使用していますか?

于 2010-04-23T16:10:44.300 に答える
0

windowOK、問題は解決しました。メイン アプリケーションのシングルトン変数と、ゲームステート マネージャーによる変数の使用との間で、名前の衝突があったようwindowです。TechZen が述べたように、コードはメソッドを持たない UIView に UIWindow メッセージを送信しようとしています。 ここでwindowは、メイン アプリケーションwindowによって UIWindow として個別に使用され、WPGameState によってそのビューポートである UIView としても使用されていたため、フレームワーク内であいまいさが生じていました。

の 2 回目の使用はwindowに名前が変更されviewport、問題が解決されました。

于 2010-04-23T18:29:23.983 に答える