applicationDidBecomeActive方法阻止我的UI

时间:2015-11-20 16:43:17

标签: ios multithreading grand-central-dispatch

我有一个方法可以在应用变为活动状态时检查剪贴板:

- (void)applicationDidBecomeActive:(UIApplication *)application {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"reload" object:nil];
    dispatch_queue_t backgroundQueue = dispatch_queue_create("clipboardQueue", 0);
    dispatch_async(backgroundQueue, ^{
        [self checkClipboard];
    });
}

但应用程序暂停了一段时间(似乎是剪贴板数据的正则表达式检查) - 如何强制此进程在另一个线程上运行?似乎我的常规GCD方法似乎没有起作用。

以下是悬挂时主线程的屏幕截图:enter image description here

以下是挂起的功能:

- (BOOL)validateUrl:(NSString *)candidate {
    NSString *urlRegEx = @"\\b(?:(?:https?|ftp):\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}0-9]+-?)*[a-z\\x{00a1}-\\x{ffff}0-9]+)*(?:\\.(?:[a-z\\x{00a1}-\\x{ffff}]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?\\b(\\/)?";
    NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", urlRegEx];
    return [urlTest evaluateWithObject:candidate];
}

这是我的checkClipboard方法:

- (void)checkClipboard {
    [[ProfileManager sharedInstance] getUserProfile:^(BOOL done, Profile *profile, NSInteger status) {
        if (done) {
            NSURL *lastUrl = [NSURL URLWithString:[[NSUserDefaults standardUserDefaults] stringForKey:@"clipboard"]];
            UIPasteboard *pb = [UIPasteboard generalPasteboard];
            NSMutableString *urlString = pb.string.mutableCopy;

            if (urlString.length) {
                if (![urlString containsString:@"http"]) {
                    urlString = [NSString stringWithFormat:@"http://%@",urlString].mutableCopy;
                }
                BOOL urlValidate = [self validateUrl:urlString];
                if (urlValidate) {
                    if (!pb.string.length || [urlString isEqualToString:lastUrl.absoluteString] || !urlValidate) {
                        return;
                    } else {

                        dispatch_async(dispatch_get_main_queue(), ^{

                           //popup toast code

                        });
                    }
                }
            }

        } else {
            NSLog(@"Not Logged In");
        }
    }];

}

1 个答案:

答案 0 :(得分:1)

似乎 checkClipboard 方法在主线程中调用 valudateURL ,如下所示:

dispatch_async(dispatch_get_main_queue(), ^{
        [self valudateURL];
});

因此,如果您希望 valudateURL 在这种情况下在非主线程中工作,则应该在没有dispatch_async的情况下调用它。

- 已编辑 -

是的,所以 getUserProfile:块在主线程中运行,如屏幕截图所示,这就是它阻止应用程序的原因。因此,如果您希望 validateUrl:complete:在后台运行,您应该使用dispatch_async调用它,如下所示:

- (void)checkClipboard {
    [[ProfileManager sharedInstance] getUserProfile:^(BOOL done, Profile *profile, NSInteger status) {
 ...
    dispatch_queue_t backgroundQueue = dispatch_queue_create("clipboardQueue", 0);
    dispatch_async(backgroundQueue, ^{
        [self validateUrl:urlString complete:^(BOOL urlValidate) {
            ...
            dispatch_async(dispatch_get_main_queue(), ^{
               //popup toast code
            });
        }];
    });
 }];
}