• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

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

[复制链接]
菜鸟教程小白 发表于 2022-12-13 02:22:19 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

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

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

//- 头文件

#import <Foundation/Foundation.h>

typedef void (^loadingCompletionBlock)(BOOL success);

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


@interface Foo : NSObject

+ (id) withCompletionBlockloadingCompletionBlock) block;

@property (assign, nonatomic) FooStatus status;

@end

//- 实现文件

@implementation Foo

- (FooStatus) status {

    __block FooStatus readStatus;

    dispatch_sync([Foo concurrentLoadingQueue], ^{
        readStatus = _status;
    });

    return readStatus;
}

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

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

    return sharedQueue;
}


+ (id)withCompletionBlockloadingCompletionBlock) completed {

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

    dispatch_async([Foo concurrentLoadingQueue], ^{

        for (int i=0; i<10000; i++)
        {
            NSLog(@"Running long tasks: %d", i);
        }

        foo.status = FooReady;

        completed(YES);

        NSLog(@"Foo status: %d (Background Thread)", foo.status);

    });


    return foo;

};

@end

然后我在主线程上调用以下代码:

 Foo* foo = [Foo withCompletionBlock:^(BOOL success) {

        dispatch_async(dispatch_get_main_queue(), ^{

             NSLog(@"Foo status: %d (Main Thread)", foo.status);

        });
    }];

    NSLog(@"Foo status: %d (Main Thread)", foo.status);

NSLog 会给我这些输出:

2014-10-01 07:09:49.606 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 1
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] ......
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Running long tasks: 9999
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:60b] Foo status: 0 (Main Thread)
2014-10-01 07:09:52.818 TestConcurrentQueue[15610:1303] Foo status: 1 (Background Thread)

0 表示状态已创建,1 已准备就绪,为什么我无法在主线程中获得正确的值?



Best Answer-推荐答案


我相信 foo 在完成 block 内是 nil 因为 foo 是作为原始方法调用的结果被创建和分配的。

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

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

Foo* foo = [[Foo alloc] init];
[foo populateWithCompletionBlock:^(BOOL success) {
    dispatch_async(dispatch_get_main_queue(), ^{
         NSLog(@"Foo status: %d (Main Thread)", foo.status);
    });
}];

NSLog(@"Foo status: %d (Main Thread)", foo.status);

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

Fooinit 方法会设置初始状态,仅此而已。

关于ios - 在多线程环境中获取正确的属性值的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26134541/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap