【问题标题】:add item to NSMutableArray inside a thread在线程内将项目添加到 NSMutableArray
【发布时间】:2021-10-17 19:16:42
【问题描述】:

我想用线程扫描照片库,当我的应用程序逻辑正常时,我想将PHAsset 添加到finalarray

NSMutableArray <PHAsset *> *finalarray = [[NSMutableArray alloc] init];

for (NSMutableArray *photoArray in arrayOfArrays) {
    dispatch_group_enter(aGroup);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        for (PHAsset *asset in photoArray) {
            [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                              options:options
                                                        resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {

                //Make some logic

                if (logic) {
                    [finalarray addObject:asset];
                }
            }];
        }
        dispatch_group_leave(aGroup);
    });
}

arrayOfArraysPHAsset 的数组。

我的代码运行良好,但有时我会遇到SIGABRT 崩溃,并且我会在代码控制台中看到此日志:

malloc: Incorrect checksum for freed object 0x1206d5968: probably modified after being freed.
Corrupt value: 0x100017580
malloc: *** set a breakpoint in malloc_error_break to debug
malloc: Incorrect checksum for freed object 0x1206d5968: probably modified after being freed.
Corrupt value: 0x100017580

【问题讨论】:

    标签: ios objective-c iphone


    【解决方案1】:

    如果您有多个线程更新一个属性,您必须同步它们的访问。你可以使用NSLock:

    NSMutableArray <PHAsset *> *finalarray = [[NSMutableArray alloc] init];
    NSLock *lock = [[NSLock alloc] init];
    
    for (NSMutableArray *photoArray in arrayOfArrays) {
        dispatch_group_enter(aGroup);
        for (PHAsset *asset in photoArray) {
            [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                              options:options
                                                        resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
    
                //Make some logic
    
                if (logic) {
                    [lock lock];
                    [finalarray addObject:asset];
                    [lock unlock];
                    dispatch_group_leave(aGroup);
                }
            }];
        }
    }
    

    或者您可以使用 GCD 队列:

    NSMutableArray <PHAsset *> *finalarray = [[NSMutableArray alloc] init];
    dispatch_queue_t queue = dispatch_queue_create("...", NULL);
    
    for (NSMutableArray *photoArray in arrayOfArrays) {
        dispatch_group_enter(aGroup);
        for (PHAsset *asset in photoArray) {
            [[PHImageManager defaultManager] requestImageDataForAsset:asset
                                                              options:options
                                                        resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
    
                //Make some logic
    
                if (logic) {
                    dispatch_async(queue, ^{
                        [finalarray addObject:asset];
                        dispatch_group_leave(aGroup);
                    });
                }
            }];
        }
    }
    

    注意,上面我假设您正在异步获取图像,在这种情况下您不需要使用全局队列,但您需要确保调用 dispatch_group_leave inside requestImageDataForAsset .

    但是,无论如何,请确保在从多个线程访问属性时同步访问(使用 GCD 队列或某些锁)。

    【讨论】:

    • 感谢@Rob 我正在使用同步来获取图像
    • 是的,我猜你一定有。但是现在您有了用于同步的 GCD 队列(无论如何您都需要),可以用一个简单的异步调用替换 serial-call-on-global-queue 模式。但随心所欲。但关键是您必须同步对从多个线程访问的变量的访问。
    猜你喜欢
    • 2011-10-30
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2012-10-01
    • 1970-01-01
    相关资源
    最近更新 更多