更新dispatch_async中的UI崩溃

时间:2013-11-19 01:54:21

标签: ios

我有以下代码

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:SOMEURL];


    NSError *err;

    NSData *response = [NSURLConnection sendSynchronousRequest:urlRequest
                                             returningResponse:nil error:&err];

    if (err)
    {
        // Do some error stuff
    }

    err = nil;

    NSDictionary *downloadedDictionary = [NSJSONSerialization JSONObjectWithData:response options:0 error:&err];

    if (err)
    {
        // Do some error stuff
    }

    dispatch_sync(dispatch_get_main_queue(), ^{
        NSDictionary* item = [downloadedDictionary objectForKey:@"user"];

        NSString* name = [item valueForKey:@"name"];

        [txtName setText:name];
    });
});

但是我每次都在[txtName setText:name]上崩溃。 txtName在标题中设置并正确合成。事实上,如果我做[txtName setText:@“随机文本”]它的工作正常。我也可以做NSLog(@“%@”,名称),它会记录信息。就在我尝试将两者混合在一起时,它崩溃了。有任何想法吗?我的错误是

 Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x109c66bd0'

2 个答案:

答案 0 :(得分:1)

试试这个,并确保在例外情况下有一个Xcode断点:

dispatch_sync(dispatch_get_main_queue(), ^{
        assert(store);
        assert([store isKindOfClass:[NSDictionary class]]);
        NSString* name = [store valueForKey:@"name"];
        assert(name);
        assert([name isKindOfClass:[NSString class]]);
        assert([self.txtName isKindOfClass:[UITextField class]]); 

        [self.txtName setText:name]; // note the user of "self"
    });

答案 1 :(得分:0)

通过跳回主队列以更新UIKit对象,您已经完成了正确的操作。正如您可能从文档中注意到的那样,UIKit通常不能安全地用于后台线程或队列,但有一些例外情况,Apple会以相当混乱的特殊方式提及。

话虽如此,[store valueForKey:@"name"]似乎是一个数组,而不是一个字符串。因此,您的错误是无法验证和/或正确解析返回的JSON。如果你NSLog它(或者,如果你想确定[name class]),你应该看到它。

同样,如果你检查JSON,你可能会在结果周围看到方括号。

您可能需要以下内容:

NSString *name = nil; // or don't bother with "= nil" if using ARC
NSArray *names = [store valueForKey:@"name"];
if([names isKindOfClass:[NSArray class]] && [names count] > 0)
    name = names[0];

if(name)
    [txtName setText:name];

假设您只期待一个名字。这两个if用作验证,Objective-C完全遵循条件评估的C规则 - 如果isKindOfClass:失败,那么对count的调用将永远不会发生,因此它是安全的测试条件一侧的类型,然后在另一侧假设它。