How to name a block of code and call it in a diffe

2019-03-27 11:39发布

I use Grand Central Dispatch methods to do some executions of my app in a queue. I decide the frames for buttons in a calculation on that queue. I want my app to re-draw its scren and calculate new frames after rotation. Here is some pseudo code explanation from what i do:

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

Here what i want is, how can i give this block a name and re-use it in the

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

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

3条回答
爷的心禁止访问
2楼-- · 2019-03-27 12:20

First, never change UI outside of the main thread. So your should modify your code into something like:

dispatch_async(drawingQue, ^{
    // ...

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

Second, never change UI inside the method shouldAutorotateToInterfaceOrientation. All you have to do inside that method is return whether the view should rotate or not. For instance, in some cases where you have a view controller hierarchy, the view might not get rotated even if you return YES in shouldAutorotateToInterfaceOrientation.

So, you should call your code inside the method:

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

This can be achieved in many ways. The simplest (and the one I recommend) is to use a 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)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"];
        });
    });
}

You don't really need to call the block itself from multiple places. But if you still want to do that, there are many answers here that show you how to do that.

查看更多
欢心
3楼-- · 2019-03-27 12:27

Just make a @property that's a block, store it, and use it again 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, x-y, a, b);
    [button setTitle:@"abc"];}}
};
...
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    dispatch_async(drawingQue, ^{
        self.buttonFramesBlock(234,someOtherInt);
    });
} 
查看更多
倾城 Initia
4楼-- · 2019-03-27 12:28

Declare an instance variable of block type and use Block_copy to keep 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 the block before storing it outside of the scope of its literal (^{...}), because the original block is stored on stack and will die when the scope exits.

查看更多
登录 后发表回答