2012-03-30 13 views
7

私は、グランドセントラルディスパッチメソッドを使用して、キュー内のアプリのいくつかの実行を行います。私は、そのキューの計算でボタンのフレームを決定します。私は、私のアプリが自分のscrenを再描画し、回転後に新しいフレームを計算したいと思う。ここで私は何をすべきかからいくつかの擬似コードの説明は次のとおりです。ブロックの名前を付けて別の方法で呼び出す方法は?

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"];}} 
     }; 

ここで私が何をしたい私は

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

デリゲートメソッドでそれをこのブロックに名前を付けて再使用する方法、ありますか?たとえば、回転が風景の場合は、123の代わりにa=234を使用します。助けてください。事前のおかげで..

答えて

6

は、ブロックタイプのインスタンス変数を宣言し、ブロックを維持するためにBlock_copyを使用します。

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

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

// later call it 
myBlock(); 

// don't forget to release it in dealloc 

それは文字通りの範囲の外にそれを格納する前コピーブロックに重要です(^{...})、元のブロックがスタックに格納され、スコープが終了したときに終了するためです。

+0

それ自体がivarで保持されているブロックの 'self'または任意のivarを参照すると、保持サイクルが発生し、リークが発生することに注意してください。サイクルを壊すには、 '__block id blockSelf = self;'ポインタを使ってivarsを参照するか、_before_ 'dealloc'ブロックを解放するようにアレンジします。 –

1

わずか1ブロックです@propertyを作り、それを格納し、後で再びそれを使用します。

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

まず、メインスレッドの外でUIを変更することはありません。方法shouldAutorotateToInterfaceOrientation内のUIを変更することはありません、

dispatch_async(drawingQue, ^{ 
    // ... 

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

第二:だからあなたのような何かにあなたのコードを変更する必要があります。そのメソッド内で行う必要があるのは、ビューを回転させるかどうかを返すことだけです。たとえば、ビューコントローラ階層がある場合、YESshouldAutorotateToInterfaceOrientationに返してもビューが回転しないことがあります。

だから、あなたは、メソッド内のコードを呼び出す必要があります:

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

これは、多くの方法で達成することができます。最も簡単な(と私はお勧め1)は、標準的なObjective-Cのメソッドを使用することです:

- (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"]; 
     }); 
    }); 
} 

あなたは本当に複数の場所からブロック自体を呼び出す必要はありません。しかし、あなたがまだそれをしたいのであれば、それを行う方法を示す多くの答えがここにあります。

+0

あなたの答えは妥当だと思われますが、どうすればこのような状況に対処できますか?私がフレームを静的に決めると、回転すると恐ろしく見える – ilhnctn

+0

あらかじめありがとう。本当に良い答え - 説明。 – ilhnctn

関連する問題