调度队列和返回数据

时间:2013-01-11 10:58:55

标签: ios queue grand-central-dispatch

我正在尝试编写一个返回NSArray的方法。我的NSMutableArray(friendUsers)正确地添加了对象,但在dispatch_async之外,数组是空的。 我尝试在主队列中添加用户(如同),但数组是空的。有任何想法吗 ?谢谢你的帮助。

- (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];
}

2 个答案:

答案 0 :(得分:2)

你可以使用积木,在这种情况下它可以让你的生活更轻松。

- (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);
    });
}

...以下是调用该方法的方法:

- (void)anyMethod {

    // ... do whetever you want here before

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

    // ... or after

}

<强>编辑:

注意:这是另一种可能的解决方案,但在你的情况下,它只是暂停主线程(肯定是错误),所以你不会获得任何解决方案,但疼痛在主线程上,但是如果你在两个后台线程上,这个解决方案可以给出一个非常好的线程同步示例。

- (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];

}

答案 1 :(得分:0)

有许多策略可以解决这个问题,但是当您的操作发生在后台线程上时,返回数组不是其中之一。您可以使用NSNotificationCenter表示任务已完成并读取数组。即。

- (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
}