Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios GCD-主队列上的访问错误_Ios_Uiview_Queue_Grand Central Dispatch - Fatal编程技术网

Ios GCD-主队列上的访问错误

Ios GCD-主队列上的访问错误,ios,uiview,queue,grand-central-dispatch,Ios,Uiview,Queue,Grand Central Dispatch,请参见此代码示例: dispatch_queue_t downloadQueue=dispatch_queue_create("test", NULL); dispatch_async(downloadQueue, ^{ //do some core data fetching stuff //create UIImage //Need to go back to the mai

请参见此代码示例:

dispatch_queue_t downloadQueue=dispatch_queue_create("test", NULL);

        dispatch_async(downloadQueue, ^{

            //do some core data fetching stuff
            //create UIImage            

            //Need to go back to the main thread since this is UI related
            dispatch_async(dispatch_get_main_queue(), ^{

                    if(someView)
                    {
                        [someView addSubview:self];
                    }
                }

            });
        });
        dispatch_release(downloadQueue);
如果此代码的主线程部分运行时“someView”不存在怎么办?显然,这会导致EXC_BAD_访问崩溃,但我想知道处理这种情况的最佳方法是什么。当用户导航到需要几秒钟才能加载的页面,但在当前页面仍在加载时决定返回上一页时,通常会发生这种情况

我可以想象在尝试添加子视图之前要检查的某种全局标志,但这似乎有点不对劲

dispatch_async(downloadQueue, ^{
    UIView* v = someView;
现在,如果此时
someView
已经不存在,并且如果您使用的是ARC,
v
为零,您可以进行测试

另一方面,如果存在
someView
,并且您正在使用ARC,则
v
是对它的一个强引用,并且它不会在块嵌套的其余部分消失。然后(此时或稍后在块的主线程部分)询问
v.window
,以发现视图是否仍在界面中;如果没有,就不值得继续

// Capture a strong reference to someView, to make sure it's still around later on.
__block UIView *v = someView;

//Need to go back to the main thread since this is UI related
dispatch_async(dispatch_get_main_queue(), ^{
   [v addSubview:self]
   // Release v (assuming ARC). If nothing else has retained someView, this means
   // that someView will be deallocated - but we're on the main thread, 
   // so that's fine. What we don't want is a background dealloc.
   v = nil;
});

你不能这样做

   UIView *strongRef = whatever;
    dispatch_async(downloadQueue, ^{
       dispatch_async(dispatch_get_main_queue(), ^{
          [someView addSubview:self]
       });
       // If, by the time we get here, the dispatch to the main queue has already run,
       // then we will send a release to someView on a background thread. If it's the last
       // remaining reference - and it might be, unlikely as it is, then we just dealloced 
       // a UIView in the background. This is bad. 
    });

如果您正在使用ARC,并且
someView
被声明为
weak
引用,那么如果对象被解除分配,它将是
nil
。这将避免保留对不再存在的视图的引用的问题。这是正确的。我将属性定义为“assign”,而不是弱属性。改为“弱”解决了这个问题。将“分配”与ARC一起使用实际上是在抛弃ARC的所有优点!:)如果使用ARC,则执行以下操作:
\uuu-UIView*v=someView
可解决此问题。一旦解除分配
v
的对象引用,
v
将自动设置为
nil
。@rmaddy不是线程安全的。块运行时,
someView
的状态可能会更改。因此,没有测试是有效的:您可以说
if(v)
,并获得一个非nil
v
,但通过从另一个线程释放
v
将其从您的下方拉出。这就是为什么您应该始终通过块内的强引用重新捕获:如果它是非nil,那么它将在块的其余部分保持非nil。
   UIView *strongRef = whatever;
    dispatch_async(downloadQueue, ^{
       dispatch_async(dispatch_get_main_queue(), ^{
          [someView addSubview:self]
       });
       // If, by the time we get here, the dispatch to the main queue has already run,
       // then we will send a release to someView on a background thread. If it's the last
       // remaining reference - and it might be, unlikely as it is, then we just dealloced 
       // a UIView in the background. This is bad. 
    });