【问题标题】:How to name a block of code and call it in a different method?如何命名代码块并以不同的方法调用它?
【发布时间】:2012-04-13 21:55:14
【问题描述】:

我使用 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 .. 请帮忙。提前谢谢..

【问题讨论】:

    标签: objective-c ipad xcode4 objective-c-blocks


    【解决方案1】:

    声明一个block类型的实例变量并使用Block_copy来保留block:

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

    在将块存储在其字面量范围之外 (^{...}) 之前,复制 块很重要,因为原始块存储在堆栈中,并且在范围退出时会消失。

    【讨论】:

    • 重要的是要注意,引用self 或块内的任何 ivar 本身保存在 ivar 中将创建一个保留循环并因此产生泄漏。您可以通过 __block id blockSelf = self; 指针引用 ivars 或通过安排释放块 before dealloc 来打破循环。
    【解决方案2】:

    只需创建一个 @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);
        });
    } 
    

    【讨论】:

      【解决方案3】:

      首先,切勿在主线程之外更改 UI。因此,您应该将代码修改为:

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

      其次,永远不要在方法shouldAutorotateToInterfaceOrientation 中更改 UI。您在该方法中所要做的就是返回视图是否应该旋转。例如,在某些情况下,您有视图控制器层次结构,即使您在 shouldAutorotateToInterfaceOrientation 中返回 YES,视图也可能不会旋转。

      所以,你应该在方法中调用你的代码:

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

      您实际上并不需要从多个位置调用块本身。但是,如果您仍然想这样做,这里有很多答案可以告诉您如何做到这一点。

      【讨论】:

      • 您的回答看起来很合理,但我该如何处理这种情况?如果我静态决定框架,当它旋转时它看起来很糟糕
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-28
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2021-09-16
      相关资源
      最近更新 更多