【问题标题】:Objective-C: How to use memory management properly for asynchronous methodsObjective-C:如何为异步方法正确使用内存管理
【发布时间】:2010-04-23 12:50:45
【问题描述】:

我需要调用一个启动一些异步代码的方法

MyClass* myClass = [[MyClass alloc] init];
[myClass startAsynchronousCode];

现在我不能简单地释放它,因为这会导致错误,因为代码仍在运行:

[myClass release];  // causes an error

处理内存的最佳方法是什么?

【问题讨论】:

    标签: objective-c memory-management asynchronous


    【解决方案1】:

    您可以让 -[MyClass startAsynchronousCode] 调用回调:

    typedef void(*DoneCallback)(void *);
    
    -(void) startAsynchronousCode {
      // Lots of stuff
      if (finishedCallback) {
        finishedCallback(self);
      }
    }
    

    然后像这样实例化一个 MyClass:

    MyClass *myClass = [[MyClass alloc] initWith: myCallback];
    

    myCallback 可能如下所示:

    void myCallback(void *userInfo) {
      MyClass *thing = (MyClass *)userInfo;
      // Do stuff
      [thing release];
    }
    

    【讨论】:

    • 当'myCallback'方法结束时,代码的执行不会返回到调用回调的方法的末尾:刚刚发布的'startAsynchronousCode'?
    • 是的,这就是为什么在调用回调之前你真的完成很重要。除非您在回调后引用 self ,否则您不会遇到任何访问冲突。
    • 我想你在问“startAsynchronousCode 是如何异步的?”在你的评论中?上述习惯用法适用于创建线程并从该新线程中运行 startAsynchronousCode。
    【解决方案2】:

    你是如何调用异步代码的?如果你使用NSThread +detachNewThreadSelector:toTarget:withObject:,你会发现目标对象一直被线程保留,直到它终止然后被释放。所以你可以在异步消息之后立即释放对象。

    例如

    @implementation MyClass
    
    -(void) startAsynchronousCode
    {
        [NSThread detachNewThreadSelector: @selector(threadMain:) toTarget: self withObject: nil];
    }
    
    -(void) threadMain: (id) anObject
    {
        NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
        // do stuff
        [pool drain];
    }
    @end
    

    有了以上内容,下面的代码就完全安全了:

    MyClass* myClass = [[MyClass alloc] init];
    [myClass startAsynchronousCode];
    [myClass release];
    

    【讨论】:

      【解决方案3】:

      您必须在 startAsynchronousCode 方法内部保留您的 myClass 对象。并在完成后在内部发布。

      此行为用于 NSURLConnection、UIAlertView 和其他异步对象。

      【讨论】:

        【解决方案4】:

        我一直做的是维护一个指向异步对象的实例变量。

        - (id)init {
            myClass = [[MyClass alloc] init];
            [myClass startAsynchronousCode];
        }
        
        - (void)myClassDidFinish:(MyClass *)myClass {
            [myClass release];
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-10
          • 2020-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多