2012-03-30 10 views
7

Uso i metodi Grand Central Dispatch per eseguire alcune esecuzioni della mia app in una coda. Decido i fotogrammi per i pulsanti in un calcolo su quella coda. Voglio che la mia app ridisegni il suo scren e calcoli i nuovi fotogrammi dopo la rotazione. Ecco alcuni pseudo codice spiegazione da quello che faccio:Come denominare un blocco di codice e chiamarlo in un altro metodo?

CGFloat a=123, b=24; 
    dispatch_async(drawingQue, ^{ 
     //needed loops to get the total button count-how many ones will be drawn et.. 
     for(int x=0;x<someCount<x++){ 
      for(int y=0;y<anotherCount;y++){ 

     //needed frame&name ect assingments 

     button.frame= CGRectMake(x+y, x-y, a, b); 
     [button setTitle:@"abc"];}} 
     }; 

Ecco quello che voglio è, come posso dare a questo blocco di un nome e di riutilizzo nel metodo delegato

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
} 

? Ad esempio, se la rotazione è orizzontale, voglio usare a=234 invece di 123 .. Qualsiasi aiuto per favore. Grazie in anticipo ..

risposta

6

dichiarare una variabile di tipo di blocco istanza e utilizzare Block_copy per mantenere il blocco:

@interface My { 
    void (^myBlock)(void); 
} 
@end 

myBlock = Block_copy(^{ 
    ...block code... 
}); 

// later call it 
myBlock(); 

// don't forget to release it in dealloc 

È importante copia blocco prima di riporlo fuori della portata del suo letterale (^{...}), perché il blocco originale è memorizzato nello stack e morirà quando l'oscilloscopio verrà chiuso.

+0

È importante notare che il riferimento a 'self' oa qualsiasi ivar all'interno di un blocco che è contenuto in un ivar creerà un ciclo di conservazione e quindi una perdita. Puoi interrompere il ciclo facendo riferimento a ivars tramite un puntatore '__block id BlockSelf = self;' oppure disponendo il blocco _before_ 'dealloc'. –

1

Basta fare un @property che è un blocco, conservarlo e utilizzarlo in un secondo momento:

typedef void (^MyBlock)(CGFloat, CGFloat); 
... 
@property(readwrite, copy) MyBlock buttonFramesBlock; 
... 
@synthesize buttonFramesBlock; 
... 
self.buttonFramesBlock = ^(CGFloat a, CGFloat b){ 
    //needed loops to get the total button count-how many ones will be drawn et.. 
    for(int x=0;x<someCount<x++){ 
     for(int y=0;y<anotherCount;y++){ 

    //needed frame&name ect assingments 

    button.frame= CGRectMake(x+y, x-y, a, b); 
    [button setTitle:@"abc"];}} 
}; 
... 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    dispatch_async(drawingQue, ^{ 
     self.buttonFramesBlock(234,someOtherInt); 
    }); 
} 
1

In primo luogo, non cambiano mai interfaccia utente al di fuori del thread principale. Così il vostro dovrebbe modificare il codice in qualcosa di simile:

dispatch_async(drawingQue, ^{ 
    // ... 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     button.frame= CGRectMake(x+y, x-y, a, b); 
     [button setTitle:@"abc"]; 
    }); 
}); 

In secondo luogo, mai cambiare interfaccia utente all'interno del metodo shouldAutorotateToInterfaceOrientation. Tutto quello che devi fare all'interno di quel metodo è restituire se la vista deve ruotare o meno. Ad esempio, in alcuni casi in cui si dispone di una gerarchia di controller di visualizzazione, la vista potrebbe non essere ruotata anche se si restituisce YES in shouldAutorotateToInterfaceOrientation.

Quindi, si dovrebbe chiamare il codice all'interno del metodo:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

Ciò può essere ottenuto in molti modi. Il più semplice (e quello mi raccomando) è quello di utilizzare un metodo di Objective-C di serie:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 
{ 
    if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) { // landscape 
     [self rotateButtonWithA:234 b:24]; 
    } else { // portrait 
     [self rotateButtonWithA:123 b:24]; 
    } 

} 

- (void)rotateButtonWithA:(CGFloat)a b:(CGFloat)b 
{ 
    dispatch_async(drawingQue, ^{ 
     // ... 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      button.frame= CGRectMake(x+y, x-y, a, b); 
      [button setTitle:@"abc"]; 
     }); 
    }); 
} 

non si ha realmente bisogno di chiamare il blocco stesso da più luoghi. Ma se vuoi ancora farlo, ci sono molte risposte qui che ti mostrano come farlo.

+0

La tua risposta sembra ragionevole ma come posso gestire questa situazione? Se decido staticamente i fotogrammi, quando ruotano sembra orribile – ilhnctn

+0

Grazie in anticipo. Davvero una buona risposta-spiegazione. – ilhnctn

Problemi correlati