I want to scan the Photo library with threads, when my app logic is ok I want to add the PHAsset
to 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);
});
}
arrayOfArrays
is array of array of PHAsset
.
My code works fine, but sometimes I get a SIGABRT
crash and I get this log in code console:
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
CodePudding user response:
If you have multiple threads updating a property, you must synchronize their access. You can use a 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);
}
}];
}
}
Or you can use a GCD queue:
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);
});
}
}];
}
}
Note, above I assume you are fetching your images asynchronously, in which case your use of the global queue is unnecessary, but you need to make sure to call dispatch_group_leave
inside the requestImageDataForAsset
.
But, regardless, make sure you synchronize your access (either with GCD queue or some lock) when accessing properties from multiple threads.
CodePudding user response:
Try synchronizing your code with a mutex:
#import <pthread.h>
...
NSMutableArray <PHAsset *> *finalarray = [[NSMutableArray alloc] init];
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
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) {
pthread_mutex_lock(&mutex);
[finalarray addObject:asset];
pthread_mutex_unlock(&mutex);
}
}];
}
dispatch_group_leave(aGroup);
});
}
In case this didn't help, have you tried setting a breakpoint in malloc_error_break to debug, as your error suggests?