在外部函数中返回内部值函数

时间:2015-12-17 15:13:45

标签: ios objective-c

我有这段代码:

- (NSString *) login {

    datos=@"";

    NSString __block *variable;

    NSString *sqlQueryExisteUsuario;
    sqlQueryExisteUsuario = [[NSString alloc] initWithFormat:@"SELECT COUNT(*) FROM tableName WHERE field='value' AND field='value'"];

    SQLClient* client = [SQLClient sharedInstance];
    client.delegate = self;
    [client connect:@"serverName" username:@"username" password:@"password" database:@"database" completion:^(BOOL success) {

            [client execute:sqlQueryExisteUsuario completion:^(NSArray* results) {

            variable =   [self processLogin:results];

            NSLog(@"In: %@",variable);


            [client disconnect];


            }];

    }];    

    NSLog(@"Out: %@",variable);

    return nil;

}

- (NSString *)processLogin:(NSArray*)data
{

    existeArray = [NSMutableArray array];

    for (NSArray* table in data)
        for (NSDictionary* row in table)
            for (NSString* column in row)


                [existeArray addObject:row[column]];


    NSString *existe=existeArray[0];


    if([existe isEqualToString:@"1"])
    {

        datos=@"yes";

    }else{

        datos=@"no";

    }

    return datos;

}

NSLog的第一次调用中,以In开头,值显示。在以Out开头的第二个调用中,该值未显示。为什么呢?

2 个答案:

答案 0 :(得分:1)

您的connect是异步方法,因此NSLog...行将早于completion阻止执行。所以,你还必须使用块:

- (NSString *) loginWithCompletion:(void(^)(NSString *result))handler
 {    
    datos=@"";

    NSString *sqlQueryExisteUsuario;
    sqlQueryExisteUsuario = [[NSString alloc] initWithFormat:@"SELECT COUNT(*) FROM tableName WHERE field='value' AND field='value'"];

    SQLClient* client = [SQLClient sharedInstance];
    client.delegate = self;
    [client connect:@"serverName" username:@"username" password:@"password" database:@"database" completion:^(BOOL success) {    
            if (success) {
                [client execute:sqlQueryExisteUsuario completion:^(NSArray* results) {

                    NSString *variable =   [self processLogin:results];
                    NSLog(@"In: %@",variable);                 
                    [client disconnect];
                    if (handler) {
                        handler (variable);
                    }
                }];
            } else {
                //TODO: handle this
                if (handler) {
                    handler (nil);
                }
            }
    }];    
}

用法:

- (void)ff
{
    [self loginWithCompletion:^(NSString *variable) {
        //Do something with variable
    }];
}

答案 1 :(得分:0)

问题是你的变量是在一个完成块中设置的:variable变量(不是一个好名字,BTW!)不仅设置在一个而是两个块内 - 这就是“完成”部分你的代码 - 两者都是最好的想法(!)就像一个微型匿名函数:在这种情况下,它们在系统准备就绪时运行,而不是直接运行。

iOS将开始执行您的connect代码,然后跳至NSLog(@"Out: %@",variable),然后执行connect的完成模块,进而启动更多代码(execute ),它有自己的完成块,最终被执行。正如@rmaddy在下面的评论中所说,技术名称是异步代码:块内的位不会立即执行,这样系统可以在等待任务完成时继续执行其他操作。

所以正在运行的订单是:

1)您声明variable

2)你的连接代码开始了。

3)variable被打印出来。

4)连接完成。

5)您的execute代码开始。

6)您的execute代码完成。

7)variable被设置为最终值。