2010-04-23 11 views
1

Je ne crains pas que Google ait été capable de sauver mon hyde. Je semble avoir une erreur SIGABRT à chaque fois que je touche l'écran du téléphone, sur n'importe quel UIView. Les messages de la console de débogage cette erreur avant la SIGABRT:SIGABRT sur n'importe quelle touche 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' 

(ce n'est pas mon appel spécifique à _exclusiveTouchView, bien sûr.)

Je signalerais volontiers un code, mais la vérité est que je ne peux pas trouver (ou devinez) d'où vient ce problème. Cela ne se produit pas sur un seul UIView, mais sur tous les UIViews de ma pile. Je peux résumer la logique d'affichage, cependant, peut-être que cela va faire la lumière. Par conséquent, l'application est créée et une interface utilisateur est allouée. Un seul viewcontroller est alors alloc'd, ce qui fait et ajoute son propre self.view vide, auquel les autres UIViews, représentant les différents états du jeu, sont attachés.

Il est intéressant de noter que cette erreur ne se produit PAS sur le simulateur, mais se produit régulièrement sur le périphérique. Et je devrais également mentionner que l'application n'a pas encore de remplacer/utiliser l'un des touchesBegan:/Ended:/Moved: etc ... En d'autres termes, cette erreur se produit sans ces méthodes dans le code.

Je ne comprends vraiment pas d'où vient cette erreur ... Des suggestions?

EDIT pour le code demandé est ici un état simplifié qui génère encore SIGABRT touch:

#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 

et si vous avez besoin de voir des parties de la sous-classe WPGameState de UIView, il peut être trouvé ici pour économiser la longueur du message: http://tinypaste.com/732bb

+0

Veuillez fournir le code de sous-classe UIView le plus simple qui reproduit le problème. Nous serons en mesure d'aider à partir de là. –

+0

Je ne sais pas si elle est directement liée, mais en utilisant une vue singleton est définitivement abus de singleton. Les vues devraient être stupides et interchangeables. Chaque vue doit avoir assez de logique pour gérer ses besoins d'affichage immédiat. Ils ne devraient pas avoir une logique d'application critique en eux telle qu'une seule par application doit exister. Vous devez repenser votre conception. – TechZen

+0

@TechZen - en termes de conception, ce sont des vues uniques responsables de la plupart de son propre environnement qui représentent des joueurs individuels. ils sont censés avoir une logique critique, mais pas la logique de l'application. Je suis d'accord, cependant, les applications non-jeu devraient rester à l'écart des vues singleton. – bitcruncher

Répondre

0

Ok, problème résolu - il semble qu'il y ait eu un conflit de noms entre la variable singleton window de l'application principale, et l'utilisation par le gestionnaire de jeu de la variable window, aussi bien. Comme TechZen mentionné, Le code tente d'envoyer un message UIWindow à un UIView qui n'a pas la méthode. Ici, window a été utilisé séparément par l'application principale en tant que UIWindow et window était également utilisé par WPGameState comme sa fenêtre d'affichage, un UIView, causant une ambiguïté au sein des frameworks.

Deuxième utilisation de window a été renommé viewport, résoudre le problème.

0

Les premières pensées: _exclusiveTouchView est une variable membre de UIWindow, il apparaît le périphérique n'a pas de UIWindow dans sa hiérarchie de vue, plus précisément sa chaîne de répondeur. Assurez-vous qu'une fenêtre est bien allouée et qu'elle est la vue de niveau supérieur de votre hiérarchie de vues. Utilisez-vous Interface Builder ou lancez-vous le vôtre?

+0

roulant le mien. le délégué de l'application charge une classe singleton chargée de prendre en charge l'intégralité de l'application. c'est là qu'une UIWindow est déclarée et allouée de la façon suivante (window est une variable de classe avec une propriété retain): window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] les limites]]; [fenêtre makeKeyAndVisible]; à partir de ce moment, le contrôleur de vue est chargé, fait son propre self.view et attache cela à la [fenêtre addSubview: (le seul VC self.view)] – bitcruncher

+0

Où est la fenêtre UIView \t *; installer? Pouvez-vous s'il vous plaît poster votre code de démarrage? Ce qui est habituellement dans - (void) l'application applicationDidFinishLaunching: (UIApplication *) ... À quoi est-ce que viewOutlet est initialisé? window = [le jeu de vue de jeu]; --- TIP ----- Dans votre code init, vous appelez [super init], puis ..initWithFrame (Qui appelle aussi [super init] .Ce n'est pas bon, juste la sous-classe (id) initWithFrame :(CGRect) aRect ou n'appelle pas explicitement [super init] – gnasher

+0

La fenêtre UIWindow * a été déclarée comme variable de classe dans l'en-tête singleton du jeu. Elle a été allouée dans le fichier d'implémentation de singleton comme décrit dans mon commentaire ci-dessus. sur initWithFrame appelant super init.J'avais des doutes à ce sujet, mais a pris une chance. (+1) – bitcruncher

1

Je pense que le problème est que quelque part vous assignez une vue à une propriété qui devrait contenir une fenêtre. Le code tente d'envoyer un message UIWindow à un UIView qui n'a pas la méthode. (UIWindow est une sous-classe de UIView.)

Je ne vois pas la cause immédiate, mais son application présente de graves problèmes de conception. Vous avez une sous-classe UIView de WPGameState qui possède elle-même une propriété UIView appelée window. Cela casse gravement le modèle de conception Model-View-Controller.

Aucune logique de WPGameState ou de IntroStateView n'appartient à une vue, cette logique appartient à un contrôleur de vue. Vous devez avoir un seul contrôleur de vue qui gère les deux vues et gère leur affichage, les minuteurs, etc. Les vues doivent uniquement savoir comment se dessiner en réponse aux commandes du contrôleur de vue.

(Et pourquoi la suppression est-il explicative un singleton vue? Ce genre d'abus singleton qui obtient singletons interdit d'utilisation dans certains magasins.

L'état du jeu ne devrait pas non plus être dans une vue ou un contrôleur de vue mais devrait plutôt se trouver dans son propre objet de modèle de données personnalisé.

Le type de problème que vous voyez est pourquoi MVC est utilisé en premier lieu. En entassant tellement de logique dans vos vues, vous pouvez déclencher une cascade d'erreurs imprévisibles en touchant simplement l'interface. Si votre conception était plus modulaire avec une séparation claire des fonctions, vous sauriez automatiquement d'où venait ce problème.

+0

@TechZen - ok, je vois d'où vous venez, bien que je ne sois pas d'accord ici, j'ai un contrôleur de vue en cours d'exécution en tant que le serveur d'affichage, tandis que les vues (individuelles et uniques), implémentées via des singletons, sont attachées à l'auto-vue du serveur d'affichage, au besoin, c'est pourquoi la classe ne tient pas de logique critique, sauf pour la rotation des périphériques et gestion de vue néralisée. dans ce magasin, nous respectons l'approche MVC pour certaines tâches, mais ce n'est pas l'un d'entre eux. cependant ... je serais ravi d'apporter votre réponse ici parce que cela m'a aidé à trouver le vrai bug. – bitcruncher

+0

Je ne vous dirai pas votre entreprise mais je vous conseillerais de faire correspondre votre conception à l'API. Je peux dire à partir de votre terminologie que vous venez d'un environnement C++ fort (ou similaire) et que vous essayez de mapper cette expérience sur cette API. Objective-C et l'API sont assez souples pour que vous puissiez faire ce que vous voulez, mais si vous ne construisez pas autour d'une conception MVC forte, vous combattrez l'API complètement au lieu de vous laisser vous aider. – TechZen