gpt4 book ai didi

ios - 究竟什么代码必须放在 iOS 的主线程上?

转载 作者:行者123 更新时间:2023-11-29 11:02:55 24 4
gpt4 key购买 nike

有人可以向我解释一下在 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 上安排了一些按钮。我发现我能够“包装”我认为对 dispatch_async(dispatch_get_main_queue(), ^{}); 中的 ui 渲染至关重要的任何代码,然后我可以将此处显示的所有代码放在其中if(completion){} 在加载 q 上。

这两个选项都有效,我测量了性能并发现我得到了相似的结果。

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

如何使用线程最大限度地提高性能?

究竟什么应该进入主线程?在方法 populateScrollViewWithArray 中,我执行了以下操作:

            dispatch_async(dispatch_get_main_queue(), ^{

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

但我做了一些事情,比如创建标签、创建按钮并在加载 q 上添加手势(没有明确地将它们包围在 dispatch_async(dispatch_get_main_queue(), ^{});

除了“阅读文档”之外,谁能给我一个简明的解释,因为我通常会发现 Apple 文档冗长冗长。有点像这个问题.....

最佳答案

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

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

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

If a view controller is referenced in a block that executes on a secondary queue, that view controller may be released (and dealloc'd) outside the main queue. This is true even if the actual block is scheduled on the main thread. ... UIKit view controllers should only be accessed on the main thread, so the snippet above may lead to subtle and hard to trace bugs.

您的代码在后台线程上运行的( block 引用的) block 中捕获 selfgesture,这意味着它们可能会在后台线程上释放,这可能偶尔会崩溃。

其他问题:

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

关于ios - 究竟什么代码必须放在 iOS 的主线程上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15035243/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com