Ios 如何在另一个对象中保留运行异步任务的对象并成功运行异步任务? 我分别有两个类A和类B的对象 ClassB包含一个很大的方法,我想在后台异步运行它,或者说其他异步线程 我正确地保留了ClassA的object,但是,在ClassA的object中我有一个ClassB的object属性。这有助于我保留ClassB的对象,直到其异步方法完成

Ios 如何在另一个对象中保留运行异步任务的对象并成功运行异步任务? 我分别有两个类A和类B的对象 ClassB包含一个很大的方法,我想在后台异步运行它,或者说其他异步线程 我正确地保留了ClassA的object,但是,在ClassA的object中我有一个ClassB的object属性。这有助于我保留ClassB的对象,直到其异步方法完成,ios,objective-c,asynchronous,objective-c-blocks,Ios,Objective C,Asynchronous,Objective C Blocks,问题:当我在主线程上运行以下代码时,它运行正常,但当我将长时间运行的方法放在异步线程中时,objectB立即被解除分配,并且什么也没有发生 @interface ClassA : NSObject @property(nonatomic, strong) ClassB *objB; @implementation ClassA -(void)createAndExecuteB { self.objB = [ClassB getNewAndExecute]; }

问题:当我在主线程上运行以下代码时,它运行正常,但当我将长时间运行的方法放在异步线程中时,objectB立即被解除分配,并且什么也没有发生

 @interface ClassA : NSObject

 @property(nonatomic, strong) ClassB *objB;

 @implementation ClassA

 -(void)createAndExecuteB
 {
     self.objB = [ClassB getNewAndExecute];
 }


 @interface ClassB

 +(ClassB *)getNewAndExecute;

 @end

 @implementation ClassB

 -(void)timeConsumingTask
 {
    //statements
 }

+(ClassB *)getNewAndExecute
{
     ClassB * __block objB = [[ClassB alloc] init];

   //Here is my issue. If I remove this dispatch code and just call
   // the timeConsumingTask method, then everything works well (blocking
   // the UI thread for a while but completing the tasks properly).
   // but if I keep the dispatch code, then this object gets instantly
   // deallocated and nothing runs
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0) ,^{
          [objB timeConsumingTask];
 });

 return objB;
 }
  @end

此代码应该可以正常工作,所以问题一定出在您没有告诉我们的地方

你可能是

  • 直接调用
    [ClassB getNewAndExecute]
    ,而不是通过
    [classA createAndExecuteB]
  • 在任务的整个过程中,不要像您认为的那样保留实例的属性
  • 在同一个
    classA
    实例上多次调用
    [classA createAndExecuteB]
    ,这将覆盖您试图保留的
    self.classB
  • 值得注意的是,您没有显示在
    timeConsumingTask
    结束时发生的情况。
    ClassA
    或保留
    ClassA
    的任何东西如何知道
    timeConsumingTask
    已完成?这是您必须释放
    ClassB
    实例的时间,因此它很重要

    检查1应该很容易

    要选中2,请将
    dealloc
    方法添加到
    ClassA
    ClassB
    中,并添加
    NSLog
    语句或在它们上设置断点,以便您可以看到对象何时被解除分配

    要选中3,请在
    createAndExecuteB
    中添加一个
    NSLog
    ,以便查看您接到的电话数量

    这是一个很好的技巧,可以打印对象的指针,这样您就可以看到您是否无意中使用了实例:

    NSLog(@"%p %p", (void *)self, (void *)self.classB);
    

    为什么要使用uu块?我使用了u块,这样可以从dispatch async的void块修改objB变量,还可以调用方法“timeConsumingTask”@CodenameLambda1,但您没有在块内修改
    objB
    ,因此没有理由使用
    \uu块
    。如果在块内执行类似于
    objB=…
    的操作,则需要
    \uu块
    。@CodenameLambda1 objB变量是指针-它不会在块中修改(至少不应该修改)。如果修改objB的属性,就不需要将其标记为_block,我知道,但是我在实际代码中从异步块设置了对objB的某些更改,因此,我在这里保留了相同的设置。需要注意的是,即使不保留_块,也会导致相同的即时释放行为。但是,是的,我在ClassB中添加了dealloc方法,它会立即打印出来。不会多次运行这些方法。objB正确保留。如您所见,如果我只是删除dispatch_async,那么一切都会运行得很好。但是,我放置了dispatch_async,这样就不会阻塞UI线程。在ObjB中,还有一个NSI通知,我会触发,objA会监听。我通过调用dispatch_get_main_队列在timeConsumingTask之后触发通知。:)@代码名lambda1您是否检查了classA是否按照2中的建议正确保留?是的,Peter,它被保留了。基本上在我的实际代码中,classA是一个单例。因此,它贯穿整个应用程序。:)