2010-03-12 8 views
1

J'ai un problème fondamental avec l'utilisation de drawRect: Tout conseil serait grandement apprécié.Besoin d'aide avec drawRect:

L'application doit dessiner une variété d'images .png à des moments différents, parfois avec animation, parfois sans.

Un objectif de conception que j'espérais respecter est d'avoir le code à l'intérieur de drawRect: très simple et «bête» - c'est-à-dire juste faire du dessin et aucune autre logique d'application.

Pour dessiner l'image, j'utilise la méthode drawAtPoint: UIImage. Comme cette méthode ne prend pas de CGContext comme paramètre, elle ne peut être appelée que dans la méthode drawRect:. J'ai donc:

- (void)drawRect:(CGRect)rect { 

[firstImage drawAtPoint:CGPointMake(firstOffsetX, firstOffsetY)]; 

} 

Tout bien et dandy pour une image. Pour dessiner plusieurs images (au fil du temps) l'approche que j'ai prise est de maintenir un tableau de dictionnaires avec chaque dictionnaire contenant une image, l'emplacement du point à dessiner et un drapeau pour activer/supprimer le dessin pour cette image. J'ajoute des dictionnaires au tableau au fil du temps et déclenche le dessin via la méthode setNeedsDisplay: de UIView. L'utilisation d'un tableau de dictionnaires me permet de reconstituer complètement l'affichage entier à tout moment. drawRect: devient maintenant:

- (void)drawRect:(CGRect)rect { 


for (NSMutableDictionary *imageDict in [self imageDisplayList]) { 
    if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) { 
    [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]]; 
    [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"]; 
    } 
} 
} 

Toujours OK. Le code est simple et compact. L'animation c'est là que je rencontre des problèmes. Le premier problème est où puis-je mettre le code d'animation? Est-ce que je le mets dans UIView ou UIViewController? Si dans UIView, est-ce que je le mets dans drawRect: ou ailleurs? Parce que l'animation réelle dépend de l'état général de l'application, je besoin d'instructions switch imbriquées qui, si elles sont mises en drawRect :, ressemblerait à quelque chose comme ceci:

- (void)drawRect:(CGRect)rect { 

for (NSMutableDictionary *imageDict in [self imageDisplayList]) { 
    if ([[imageDict objectForKey:@"needsDisplay"] boolValue]) { 

    switch ([self currentState]) { 
    case STATE_1: 
    switch ([[imageDict objectForKey:@"animationID"] intValue]) { 
     case ANIMATE_FADE_IN: 
     [self setAlpha:0.0]; 
     [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil]; 
     [UIView setAnimationDelegate:self]; 
     [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; 
     [UIView setAnimationDuration:2]; 
     [self setAlpha:1.0]; 
     break; 
     case ANIMATE_FADE_OUT: 
     [self setAlpha:1.0]; 
     [UIView beginAnimations:[[imageDict objectForKey:@"animationID"] intValue] context:nil]; 
     [UIView setAnimationDelegate:self]; 
     [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 
     [UIView setAnimationDuration:2]; 
     [self setAlpha:0.0]; 
     break; 
     case ANIMATE_OTHER: 
     // similar code here 
     break; 
     default: 
     break; 
    } 
    break; 
    case STATE_2: 
    // similar code here 
    break; 
    default: 
    break; 
    } 
    [[imageDict objectForKey:@"image"] drawAtPoint:[[imageDict objectForKey:@"location"] CGPointValue]]; 
    [imageDict setValue:[NSNumber numberWithBool:NO] forKey:@"needsDisplay"]; 
    } 
} 

[UIView commitAnimations]; 

} 

En outre, pour faire de multiples animations successives fonctionnent correctement , il devrait y avoir un mécanisme de contrôle externe impliquant le délégué d'animation animationDidStop: callback qui définirait les entrées needsDisplay dans les dictionnaires pour permettre/supprimer le dessin (et l'animation).

Le point que nous sommes maintenant est que tout commence à avoir l'air très laid. Plus précisément:

  • drawRect: commence à se gonflent rapidement et contiennent du code qui ne sont pas « dessin juste » Code
  • le UIView a besoin conscience implicite de l'état d'application
  • l'ensemble du processus de dessin est maintenant réparti sur trois méthodes à un minimum

Et sur le point de ce post: comment puis-je faire mieux? Que recommanderaient les experts en termes de structure globale? Comment puis-je conserver les informations sur l'état de l'application hors de la vue? Est-ce que je regarde ce problème dans la mauvaise direction? Y a-t-il une approche complètement différente que je devrais envisager?

Répondre