2010-07-27 5 views
0

Ours avec moi, celui-ci est difficile à expliquer. J'espère qu'un héros sait ce qui se passe ici. Un peu d'histoire nécessaireProblème Cocoa Confound - le programme se bloque sauf s'il y a un appel de méthode non reconnu

Un de mes objets cacao, "Ball" représente un petit graphique. Cela n'a de sens que dans une vue. Dans certaines méthodes de la boule, il demande à la vue de redessiner. Plus important encore, il demande à la vue de redessiner chaque fois que le paramètre de position de la balle est défini. Ceci est réalisé dans le setter.

est ici la bouche pleine, comme le suggère:

Dans View.m

- (void)mouseUp:(NSEvent *)theEvent { 
    if (![runnerPath isEmpty]) { 
     [walkPath removeAllPoints]; 
     [walkPath appendBezierPath:runnerPath]; 
     [runnerPath removeAllPoints]; 

     [[self held] setStep:0]; 
     [[self held] setPath:walkPath]; 
     [NSTimer scheduledTimerWithTimeInterval:.01 target:[self held] selector:@selector(pace) userInfo:nil repeats:YES]; 

     } 
} 

Dans Ball.m

- (void)pace { 
    CGFloat juice = 10; 
    BOOL loop = YES; 

    while (loop) { 
     if ([self step] == [[self path] elementCount]) { 
      if ([[self timer] isValid]) { 
       [[self timer] invalidate]; 
      } 
      [[self path] removeAllPoints]; 
//   @throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]); 
     } 

     if (loop) { 
      CGFloat distance; 
      NSPoint stepPoint; 

      if ([[self path] elementCount] > 0) { 
       NSPoint returnPoints[2]; 
       [[self path] elementAtIndex:[self step] associatedPoints:returnPoints]; 
       stepPoint = returnPoints[0]; 
       distance = pixelDistance([self position], stepPoint); 
      } 

      if (distance <= juice) { 
       [self setPosition:stepPoint]; 
       if (distance < juice) { 
        juice -= distance; 
        loop = YES; 
        [self setStep:[self step]+1]; 
       } else { 
        loop = NO; 
       } 
      } else {    
       NSPoint cutPoint = moveAlongBetween([self position], stepPoint, juice); 
       [self setPosition:cutPoint]; 

       loop = NO; 
      } 

     } 
    } 

} 
+1

Avez-vous essayé d'exécuter votre application dans le débogueur, puis d'interrompre l'exécution lorsque le blocage se produit et d'examiner la pile d'appels? – sbooth

+0

Quel niveau d'optimisation utilisez-vous? Je me demande si la boucle vide avec l'utilisation de '-allObjects' est supprimée par le compilateur. –

+0

En regardant le débogueur maintenant, et googling frénétiquement. Je suis embarrassant peu familier avec comment cela fonctionne. Merci pour votre aide, de toute façon. Je vais voir ce que je peux faire de la pile d'appels. –

Répondre

1

pouvez-vous également dire comment vous gérez les exceptions? car normalement un sélecteur non reconnu mettra fin à votre programme. Peut-être avez-vous besoin d'une exception plutôt que d'un sélecteur non reconnu. Essayez:

@throw([NSException exceptionWithName:@"test" reason:@"reason" userInfo:nil]); 

Si cela corrige également, vous faites quelque chose après ce code qui gèle l'application.

modifier: merci pour la mise à jour du code.

Il y a des trucs bizarres ici! Je ne vais pas réécrire le tout, alors voici quelques pointeurs:

  • tout d'abord: vous êtes en boucle dans une routine qui est appelée à partir d'une boucle de minuterie. Est-ce que c'est prévu? Il n'y a aucun moyen de suspendre l'exécution dans cette boucle while(), donc cela se produira en un clin d'œil. Vous devez conserver certaines informations d'état dans la classe. Par exemple. ajouter un compteur de boucle chaque fois que pace est appelée. Seconde: si vous démarrez une minuterie, elle appellera votre sélecteur avec le minuteur comme argument. Donc, définissez la fonction comme -(void)pace:(NSTimer*)timer, et utilisez timer, pas [self timer] (ce dernier ne sera pas votre temporisateur de toute façon, si vous ne l'attribuez pas!)
  • troisième: vous tirez 100 fois par seconde. C'est beaucoup, et probablement plus élevé que le taux de rafraîchissement de tout appareil pour lequel vous écrivez. Je pense que 20/sec suffit.
  • quatrième: pour être sûr, si vous changez à -(void)pace:(NSTimer*)timer, ne pas oublier d'utiliser @selector(pace:) (ne pas oublier le :)

corriger ces choses, et si elle est encore cassé, mettez à jour votre question encore et mettez dans le commentaire ainsi nous saurons. Bonne chance!

+0

L'instruction @throw le fait également. Je suis un peu novice, mais je suppose que je devrais chercher l'erreur plus loin dans la ligne? Merci de votre aide. –

+1

Ok alors il y a 2 options: 1) vous renflouer à temps pour ne pas geler l'application plus loin sur la route 2) votre gestion des exceptions fait quelque chose d'autre qui empêche le gel. Heureusement, il existe un excellent moyen de renoncer à la fonction * sans * l'exception, appelée «retour». Si le code ne gèle pas alors, il doit être quelque chose passé ce point dans la même fonction. Si ça gèle, soit vous dépendez de la magie qui se passe dans la gestion des exceptions, * ou * il y a quelque chose de buggé qui se passe après le point où vous appelez cette fonction, avant de gérer l'exception. – mvds

+1

mais cela devient un peu hors de contrôle. Pour raccourcir les choses: êtes-vous sûr que vous ne définissez pas 'self.position = ...;' dans le setter? S'il vous plaît 'NSLog (" quelque chose ");' dans 'setPosition' pour voir si vous n'êtes pas dans une boucle infinie. – mvds

1

Essayez d'appeler

for (NSView *each in [self views]) { 
    ... 
} 

Je suppose que views est un arr oui, l'énumération si rapide s'applique directement et il n'est pas nécessaire d'appeler allObjects.

Quelques autres points.

  1. Avez-vous défini un point d'arrêt global de objc_exception_throw? Cela s'appliquera à tous les projets Xcode et est si utile que je suis surpris qu'il ne soit pas défini par défaut.
  2. Vous dites que vous avez regardé la console pour des erreurs. Je suppose donc que vous n'avez pas défini de point d'arrêt sur le code et que vous ne l'avez pas vu pour voir exactement ce qui se passe lorsque votre exécution atteint ce point? Jetez un oeil à la Xcode Debugging Guide
+0

+1 Il dit que 'views' est un NSSet, donc l'énumération rapide s'applique là aussi. –

+0

Comment cela a-t-il quelque chose à voir avec le gel de l'application? – mvds

+0

Je n'ai pas fait la chose breakpoint. Comment cela aiderait-il? –

Questions connexes