简体   繁体   中英

dispatch_queue and return data

I'm trying to write this method that returns an NSArray . My NSMutableArray (friendUsers) adds the objects right, but outside the dispatch_async the array is empty. I try to add the users in the main queue ( as ashowed) but the array is empty to. Any ideas ? Thanks for all your help.

- (NSArray *)checkUsersInGroup {

    NSMutableArray *friendUsers = [[NSMutableArray alloc] init];

    dispatch_queue_t checkUSers = dispatch_queue_create("CheckUsers", NULL);
    dispatch_async(checkUSers, ^{

        NSArray *totalUsers = [VVDataRead lecturaDades];
        NSArray *usersToSearch = [_grup objectForKey:@"groupFriends"];

        for (NSString *tempUserId in usersToSearch){
            for (NSDictionary *user in totalUsers){
                NSString *id = [user objectForKey:@"id"];
                    if ([tempUserId isEqualToString:id])
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [friendUsers addObject:user];
                        });
            }
        }

    });
    NSLog(@"people:%@",friendUsers);
    return [friendUsers copy];
}

you can use blocks, it can make your life easier in this case.

- (void)checkUsersInGroupWithCompleteBlock:(void(^)(NSMutableArray * resultArray))completeBlock {

    NSMutableArray *friendUsers = [[NSMutableArray alloc] init];

    dispatch_queue_t checkUSers = dispatch_queue_create("CheckUsers", NULL);
    dispatch_async(checkUSers, ^{

        NSArray *totalUsers = [VVDataRead lecturaDades];
        NSArray *usersToSearch = [_grup objectForKey:@"groupFriends"];

        for (NSString *tempUserId in usersToSearch){
            for (NSDictionary *user in totalUsers){
                NSString *id = [user objectForKey:@"id"];
                if ([tempUserId isEqualToString:id])
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [friendUsers addObject:user];
                    });
            }
        }

        // call the complete block with the result when you finished
        if (completeBlock) completeBlock(friendUsers);
    });
}

...and here is how you can call the method:

- (void)anyMethod {

    // ... do whetever you want here before

    [self checkUsersInGroupWithCompleteBlock:^(NSMutableArray *resultArray) {
        NSLog(@"%@", resultArray);
    }];

    // ... or after

}

EDITED:

NOTE: here is another possible solution, but in your case it just suspends the main thread (which is definitely bad ), so you won't gain anything with this solution but pain on the main thread, but if you are on two background threads, this solution can give a very nice example of synchronisation between the threads.

- (NSArray *)checkUsersInGroup {

    NSMutableArray *friendUsers = [[NSMutableArray alloc] init];

    // our semaphore is here
    dispatch_semaphore_t _semaphore = dispatch_semaphore_create(0);

    dispatch_queue_t checkUSers = dispatch_queue_create("CheckUsers", NULL);
    dispatch_async(checkUSers, ^{

        NSArray *totalUsers = [VVDataRead lecturaDades];
        NSArray *usersToSearch = [_grup objectForKey:@"groupFriends"];

        for (NSString *tempUserId in usersToSearch){
            for (NSDictionary *user in totalUsers){
                NSString *id = [user objectForKey:@"id"];
                if ([tempUserId isEqualToString:id])
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [friendUsers addObject:user];
                    });
            }
        }
        // the process finished
        dispatch_semaphore_signal(_semaphore);

    });

    // ... we are wainitng for the semaphore's signal
    dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    dispatch_release(_semaphore);

    NSLog(@"people:%@",friendUsers);
    return [friendUsers copy];

}

There are number of strategies to solve this, but as your operation happens on a background thread, returning the array isn't one of them. You could use NSNotificationCenter to signal that the task as finished and read the array. ie

- (void)checkUsersInGroup {

    NSMutableArray *friendUsers = [[NSMutableArray alloc] init];

    dispatch_queue_t checkUSers = dispatch_queue_create("CheckUsers", NULL);
    dispatch_async(checkUSers, ^{

        NSArray *totalUsers = [VVDataRead lecturaDades];
        NSArray *usersToSearch = [_grup objectForKey:@"groupFriends"];

        for (NSString *tempUserId in usersToSearch){
            for (NSDictionary *user in totalUsers){
                NSString *id = [user objectForKey:@"id"];
                    if ([tempUserId isEqualToString:id])
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [friendUsers addObject:user];
                        });
            }
        }

        // Signal background task is finished
        // Make sure to add an observer to this notification
        [[NSNotificationCenter defaultCenter] postNotificationName:@"friendsAddLiteral"
                                                                object:nil];

    });
}

//this method will respond to the notification
- (void) onFriendsAdded:(NSNotification*)notif {
    //do something on the main thread
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM