菜鸟教程小白 发表于 2022-12-13 02:22:19

ios - 在多线程环境中获取正确的属性值的问题


                                            <p><p>我正在尝试在对象初始化期间卸载一些繁重的工作。我添加了一个在我完全初始化对象的所有其他实例变量时设置的状态属性。我通过以下示例简化了整个方法:</p>

<p>这是我的类 (Foo),它有我的初始化程序:</p>

<p>//- 头文件</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;

typedef void (^loadingCompletionBlock)(BOOL success);

typedef NS_ENUM(NSInteger, FooStatus) {
    FooCreated,
    FooReady,
    FooFailed,
};


@interface Foo : NSObject

+ (id) withCompletionBlock:(loadingCompletionBlock) block;

@property (assign, nonatomic) FooStatus status;

@end
</code></pre>

<p>//- 实现文件</p>

<pre><code>@implementation Foo

- (FooStatus) status {

    __block FooStatus readStatus;

    dispatch_sync(, ^{
      readStatus = _status;
    });

    return readStatus;
}

+ (dispatch_queue_t)concurrentLoadingQueue
{
    static dispatch_queue_t sharedQueue;
    static dispatch_once_t onceToken;

    dispatch_once(&amp;onceToken, ^{
      sharedQueue = dispatch_queue_create(&#34;test.loadingQueue&#34;, DISPATCH_QUEUE_CONCURRENT);
    });

    return sharedQueue;
}


+ (id)withCompletionBlock:(loadingCompletionBlock) completed {

    Foo* foo = [ init];
    foo.status = FooCreated;

    dispatch_async(, ^{

      for (int i=0; i&lt;10000; i++)
      {
            NSLog(@&#34;Running long tasks: %d&#34;, i);
      }

      foo.status = FooReady;

      completed(YES);

      NSLog(@&#34;Foo status: %d (Background Thread)&#34;, foo.status);

    });


    return foo;

};

@end
</code></pre>

<p>然后我在主线程上调用以下代码:</p>

<pre><code> Foo* foo = [Foo withCompletionBlock:^(BOOL success) {

      dispatch_async(dispatch_get_main_queue(), ^{

             NSLog(@&#34;Foo status: %d (Main Thread)&#34;, foo.status);

      });
    }];

    NSLog(@&#34;Foo status: %d (Main Thread)&#34;, foo.status);
</code></pre>

<p>NSLog 会给我这些输出:</p>

<pre><code>2014-10-01 07:09:49.606 TestConcurrentQueue Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue Running long tasks: 1
2014-10-01 07:09:52.818 TestConcurrentQueue ......
2014-10-01 07:09:52.818 TestConcurrentQueue Running long tasks: 9999
2014-10-01 07:09:52.818 TestConcurrentQueue Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue Foo status: 1 (Background Thread)
</code></pre>

<p>0 表示状态已创建,1 已准备就绪,为什么我无法在主线程中获得正确的值?</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我相信 <code>foo</code> 在完成 block 内是 <code>nil</code> 因为 <code>foo</code> 是作为原始方法调用的结果被创建和分配的。</p>

<p>一个简单的解决方案是将创建的对象作为参数传递给完成 block ,以及 <code>BOOL</code>。</p>

<p>更好的方法可能是让您的 <code>withCompletionBlock:</code> 成为实例方法而不是类方法。那么您的调用代码将类似于:</p>

<pre><code>Foo* foo = [ init];
[foo populateWithCompletionBlock:^(BOOL success) {
    dispatch_async(dispatch_get_main_queue(), ^{
         NSLog(@&#34;Foo status: %d (Main Thread)&#34;, foo.status);
    });
}];

NSLog(@&#34;Foo status: %d (Main Thread)&#34;, foo.status);
</code></pre>

<p>这样,完成 block 内的 <code>foo</code> 引用了一个实际存在的对象。</p>

<p><code>Foo</code> 的 <code>init</code> 方法会设置初始状态,仅此而已。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 在多线程环境中获取正确的属性值的问题,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/26134541/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/26134541/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 在多线程环境中获取正确的属性值的问题