块在异步线程上执行两次

Posted

技术标签:

【中文标题】块在异步线程上执行两次【英文标题】:Block gets executed twice on async thread 【发布时间】:2015-12-07 12:33:44 【问题描述】:

我有一个奇怪的问题。我有一个类在后台线程上调用另一个类中的方法,但是它在线程 2 上两次获取数据,然后一旦完成,例如将其放入线程 4。有谁知道为什么?

调用方法的类:

-(void)awakeFromNib

    NSString *swedbankRate;

    CurrencyViewHelper *currencyRates = [[CurrencyViewHelper alloc]init];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^

        swedbankRate = [currencyRates getSwedbankRates];
        NSLog(@"%@", swedbankRate);
    );

所以来自 CurrencyViewHelper 的部分是:

-(NSString *)getSwedbankRates

// Set to empty String in case there is some issue
swedbankRate = @"";

// Get Data from Swedbank
NSString *swedbankURL = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"https://www.swedbank.ee/private/d2d/payments2/rates/currency?language=EST"]
                                                 encoding:NSASCIIStringEncoding
                                                    error:nil];
NSArray *swedbankArray = [swedbankURL componentsSeparatedByString:@"<tr>"];
NSString *swedbankString = swedbankArray[18];
swedbankArray = [swedbankString componentsSeparatedByString:@"<tr>"];

NSString *swedbankDirty = swedbankArray[0];

// Check if the fetched data corresponds to RUB data
if ([swedbankDirty containsString:@"RUB"]) 

    swedbankDirty = [swedbankDirty stringByReplacingOccurrencesOfString:@"<td class=\"numeric-cell\">"
                                                             withString:@""];
    swedbankDirty = [swedbankDirty stringByReplacingOccurrencesOfString:@"\n"
                                                             withString:@""];
    swedbankDirty = [swedbankDirty stringByReplacingOccurrencesOfString:@" "
                                                             withString:@""];
    NSArray *swedbankCleanArray = [swedbankDirty componentsSeparatedByString:@"</td>"];
    swedbankDirty = swedbankCleanArray[4];

    // Set result to value fetched from internet
    swedbankRate = [NSString stringWithFormat:@"%.2f", [swedbankDirty floatValue]];


结果是

2015-12-07 14:26:29.635 Photography[60338:18355297] 71.14
2015-12-07 14:26:29.684 Photography[60338:18355293] 71.14

我无法理解它为什么会执行两次?

该方法应该做的是扫描网页的 html 代码并从整个内容中获取一个浮点数供我以后使用。是的,代码并不完美,还在学习中。欢迎任何想法。

【问题讨论】:

如果它运行了两次,那是因为awakeFromNib 被调用了两次。我会在该方法中添加一个日志以进行验证。然后我会将代码移到其他地方。 【参考方案1】:

awakeFromNib 通常不适合这种事情。您应该使用 awakeFromNib 来执行您本来想在 Interface Builder 中执行的操作,但由于某种原因不能 - 所以只是为了解决加载 nib 文件时出现的问题。

例如,如果您在不同的上下文中使用相同的类,并且如果您在代码中构建用户界面而不是使用 nib 文件,并且您的 awakeFromNib 不会在一切都了。

【讨论】:

我主要是尝试用一些数据填充标签,在我从网页获取这些数据之前,我无法做到这一点,这就是为什么我想把整个事情从 nib 中唤醒。但是视图确实加载并等待一个分裂的 secodn 值更新为新的值也不是那么糟糕。【参考方案2】:

检查awakeFromNib 是否在您的应用中被调用了两次... (see this question)

【讨论】:

【参考方案3】:

你说的都是对的。哇,这是多么愚蠢的错误。事实上,另一个班级也在调用 awakeFromNib 来做它的事情。

我将这些调用放在 viewDidLoad 方法中,它现在可以按需要工作了!伟大的!学习这种多线程东西的好方法! :)

【讨论】:

以上是关于块在异步线程上执行两次的主要内容,如果未能解决你的问题,请参考以下文章

重回博客 谈一谈Node中的异步和单线程

在后台线程上执行异步套接字

如果异步调用不一定在不同的线程上执行,阻塞异步调用如何导致死锁?

GCD - 如何在主线程上等待在主队列上执行的异步回调

java定时任务使用多线程webservcie执行了两次这是为啥?

使用异步避免重复代码