How to name a block of code and call it another way?

I use the Grand Central Dispatch methods to execute some executions of my application in the queue. I define the frames for the buttons in the calculation in this queue. I want my application to re-draw its scren and compute new frames after rotation. Here are some explanations of the pseudocode from what I am doing:

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, xy, a, b); [button setTitle:@"abc"];}} }; 

Here I want how I can give this block a name and reuse it in

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

delegate method? For example, if the turn is landscape, I want to use a=234 instead of 123 .. Any help please. Thanks in advance.

+7
source share
3 answers

Declare a block type instance variable and use Block_copy to save the block:

 @interface My { void (^myBlock)(void); } @end myBlock = Block_copy(^{ ...block code... }); // later call it myBlock(); // don't forget to release it in dealloc 

It is important to copy a block before storing it outside the scope of its literal ( ^{...} ), since the original block is stored on the stack and will die when leaving the scope.

+6
source

Just make @property that block, save it and use it later:

 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, xy, a, b); [button setTitle:@"abc"];}} }; ... - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { dispatch_async(drawingQue, ^{ self.buttonFramesBlock(234,someOtherInt); }); } 
+1
source

First, never change the interface outside the main thread. Therefore, your code should change the code:

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

Secondly, never change the interface inside the shouldAutorotateToInterfaceOrientation method. All you have to do inside this method is return whether the view should rotate or not. For example, in some cases when you have a view controller hierarchy, the view may not rotate, even if you return YES in shouldAutorotateToInterfaceOrientation .

So you have to call your code inside the method:

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

This can be achieved in many ways. The easiest (and the one I recommend) is to use the standard Objective-C method:

 - (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)ab:(CGFloat)b { dispatch_async(drawingQue, ^{ // ... dispatch_async(dispatch_get_main_queue(), ^{ button.frame= CGRectMake(x+y, xy, a, b); [button setTitle:@"abc"]; }); }); } 

You really do not need to call the block itself from several places. But if you still want to do this, there are many answers here that show how to do this.

+1
source

All Articles