1

有人请向我解释哪些代码行应该在iOS的主线上?在iOS的主线程中必须准确定位哪些代码?

我有类似如下:

- (void)asyncWorkOnLayingOutSKUs:(UILongPressGestureRecognizer *)gesture andBlock:(void (^)(BOOL))completion { 
__block NSTimeInterval totalTi = -[NSDate timeIntervalSinceReferenceDate]; 
// 
dispatch_queue_t callerQ = dispatch_get_current_queue(); 
dispatch_queue_t loadingQ = dispatch_queue_create("ff.aq", NULL); 
dispatch_async(loadingQ, ^{ 

    //Code below can be placed here and then I used: dispatch_async(dispatch_get_main_queue(), ^{ //code here that must go on main thread }); in order to make it work 

    BOOL trueBool = YES; 
    // 
    dispatch_async(callerQ, ^{ 
     totalTi += [NSDate timeIntervalSinceReferenceDate]; 
     NSLog(@"Performance: %g sec", totalTi); 
     completion(trueBool); 
     if(completion){ 

    //For now, there is no multithreading since all code is placed on main thread... 

      self.timingDate = [NSDate date]; 

      switch (self.lastButtonPressedForDragTags) { 
       case 1:{ 
        self.slotOneButtonIndex = gesture.view.tag-1; 
       } break; 
       case 2:{ 
        self.slotTwoButtonIndex = gesture.view.tag-1; 
       } break; 
       case 3:{ 
        self.slotThreeButtonIndex = gesture.view.tag-1; 
       } break; 
       case 4:{ 
        self.slotFourButtonIndex = gesture.view.tag-1; 
       } break; 
       case 5:{ 
        self.slotFiveButtonIndex = gesture.view.tag-1; 
       } break; 
      } 

      int touchedtag = gesture.view.tag; 
      UIView* thisView; 
      UIScrollView* thisScrollView; 

      switch (gesture.view.superview.superview.tag) { 
       case -1:{ 
        thisView = self.dragTagsScrollViewContainer; 
        thisScrollView = self.dragTagsScrollView; 
       } break; 
       case -2:{ 
        thisView = self.SKUTagsScrollViewContainer; 
        thisScrollView = self.SKUTagsScrollView; 
       } break; 
       case -3:{ 
        thisView = self.otherTagsScrollViewContainer; 
        thisScrollView = self.otherTagsScrollView; 
       } break; 
       case -4:{ 
        thisView = self.leftDraggedTagsScrollViewContainer; 
        thisScrollView = self.leftDraggedTagsScrollView; 
       } break; 
      } 

      UIButton *button = (UIButton*)[thisView viewWithTag:touchedtag]; 

      if(![button isSelected]){ 
       [self setButtonSelected:button]; 
      } 
      else{ 
       [self setButtonDeselected:button]; 
      } 

      //Get the position of the button RELATIVE to the superview by subtracting the content offset for x direction: 
      CGRect buttonPosition = CGRectMake(button.frame.origin.x - thisScrollView.contentOffset.x, button.frame.origin.y, button.frame.size.width, button.frame.size.height); 

      CGRect sizeOfScrollView = CGRectMake(0, 0, thisScrollView.frame.size.width, thisScrollView.frame.size.height); 

      if(CGRectContainsRect(sizeOfScrollView, buttonPosition)){} 
      else{ 
       //extend scrollview to L or R 
       CGPoint rightBottomEdgeOfButton = CGPointMake(buttonPosition.origin.x + buttonPosition.size.width, buttonPosition.origin.y + buttonPosition.size.height); 
       CGRect intersection = CGRectIntersection(sizeOfScrollView, buttonPosition); 
       float amountToMove; 
       float currentXDirectionOffset = thisScrollView.contentOffset.x; 
       CGPoint newOffset; 

       if (CGRectContainsPoint(sizeOfScrollView, rightBottomEdgeOfButton)){ 
        //Need to move Left 
        amountToMove = button.frame.size.width - intersection.size.width + 5; 
       } 
       else{ 
        //Need to move Right 
        amountToMove = -(button.frame.size.width - intersection.size.width + 5); 
       } 
       newOffset = CGPointMake(currentXDirectionOffset-amountToMove, thisScrollView.contentOffset.y); 

       [thisScrollView setContentOffset:newOffset]; 
      } 

      [self.SKUTagsScrollViewContainer removeFromSuperview]; 

      NSMutableArray* arrayToUse = [[NSMutableArray alloc]initWithArray:[self getIntersectionArray]]; 


      [self populateScrollViewWithArray:arrayToUse andScrollView:self.SKUTagsScrollView withContainer:self.SKUTagsScrollViewContainer andmaxNumberOfRowsForScrollView:6]; 

#ifdef DEBUG 
      NSLog(@"Time taken to AFTER populateScrollViewWithArray: %g and for %d controls", [[NSDate date] timeIntervalSinceDate:self.timingDate], [arrayToUse count]); 
#endif 
     } 
    }); 
}); 
dispatch_release(loadingQ); 
} 

现在显然没有什么是对装载Q和方法populateScrollViewWithArray基本上安排在一个UIScrollView一些按钮。我发现我能够'包装'任何我认为对于UI渲染至关重要的代码,然后我可以将这里显示的所有代码放在加载q上的if(completion){}内。

这两个选项都起作用,我测量了性能,发现我得到了类似的结果。

我的问题是,我是新来的iOS和我想知道:

我怎样才能最大限度地使用线程的性能?

究竟应该走到主线程?在该方法中populateScrollViewWithArray我做了以下内容:

  dispatch_async(dispatch_get_main_queue(), ^{ 

      [scrollview addSubview:scrollViewContainer]; 
      [self.view addSubview:scrollview]; 
     }); 

但我做事情喜欢创建标签,创建按钮和装载q加手势(内没有明确包围他们dispatch_async(dispatch_get_main_queue(), ^{});

任何人都可以点我除了'阅读文档'以外,我通常发现苹果文档相当长的啰嗦。有点像这个问题.....

+2

每次调用UIKit。 – 2013-02-22 23:58:09

+0

谢谢。对一个长期问题的简短回答。 – 2013-02-23 00:35:44

回答

2

一般的规则是,大多数UIKit类是不安全的使用从一个后台线程,除非文档明确说明,否则(有时文档使用不一致,有时会中断,例如,从4.0开始,UIKit绘图应该是线程安全的,但在iOS 5.x中被破坏了)。

IIRC文档还建议在后台线程上创建视图(例如通过加载笔尖)是安全的,前提是它们尚未添加到窗口中。尽管如此,我还没有对此进行浸泡测试,因此可能存在一些不安全的边缘情况(UIWebView可能就是其中之一)。

这也是略微比这更复杂,因为一些UIKit类根据GKTapper example code是不安全释放从后台线程:

如果视图控制器在一个块中引用它在辅助队列上执行, 视图控制器可以在主队列之外释放(并且释放)。 即使在主线程上调度实际块,情况也是如此。 ... UIKit视图控制器应该只能在主线程上访问,所以上面的代码片段可能会导致微妙且难以追踪错误

你的代码捕获在一个后台线程,这意味着他们可能会在后台线程,这有时可能会崩溃发布运行块(被引用的块)selfgesture

其他吹毛求疵:

  • totalTi并不需要是一个__block变量。
  • loadingQ应替换为全局队列。
  • if(completion)始终为真(completion(trueBool)在上面的行中崩溃,如果completion为NULL)。
  • 您可以将大部分代码移至VC中的完成方法,而不是具有6级缩进。
+0

非常感谢答案tc。它有帮助 – 2013-02-23 00:33:12

相关问题