Как назвать блок кода и вызвать его другим методом? - PullRequest
7 голосов
/ 30 марта 2012

Я использую методы Grand Central Dispatch для выполнения некоторых приложений моего приложения в очереди.Я определяю рамки для кнопок в расчете на эту очередь.Я хочу, чтобы мое приложение перерисовывало скрен и вычисляло новые кадры после поворота.Вот некоторые объяснения псевдокода из того, что я делаю:

 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
{
} 

метод делегата?Например, если вращение является альбомным, я хочу использовать a=234 вместо 123 .. Любая помощь, пожалуйста.Заранее спасибо ..

Ответы [ 3 ]

6 голосов
/ 30 марта 2012

Объявите переменную экземпляра типа блока и используйте 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

Важно скопировать блок перед сохранением его вне области его литерала (^{...}), потому что оригинальный блок хранится в стеке и умрет при выходе из области.

1 голос
/ 30 марта 2012

Во-первых, никогда не меняйте интерфейс вне основного потока.Таким образом, вы должны изменить ваш код на что-то вроде:

dispatch_async(drawingQue, ^{
    // ...

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

Во-вторых, никогда не меняйте интерфейс внутри метода shouldAutorotateToInterfaceOrientation.Все, что вам нужно сделать внутри этого метода, это вернуть, должно ли представление вращаться или нет.Например, в некоторых случаях, когда у вас есть иерархия контроллера представления, представление может не поворачиваться, даже если вы вернете YES в shouldAutorotateToInterfaceOrientation.

Итак, вы должны вызвать свой код внутри метода:

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

Этого можно достичь разными способами.Самый простой (и тот, который я рекомендую) - использовать стандартный метод 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"];
        });
    });
}

Вам не нужно вызывать сам блок из нескольких мест.Но если вы все еще хотите это сделать, здесь есть много ответов, которые покажут вам, как это сделать.

1 голос
/ 30 марта 2012

Просто сделайте @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);
    });
} 
...