applicationDidBecomeActive 方法阻塞了我的 UI
applicationDidBecomeActive method blocking my UI
我有一种方法可以在应用程序激活时检查剪贴板:
- (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 方法似乎不起作用。
这是我挂机时主线程的截图:
这是它挂起的函数:
- (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");
}
}];
}
似乎 checkClipboard 方法在主线程中调用了 valudateURL,像这样:
dispatch_async(dispatch_get_main_queue(), ^{
[self valudateURL];
});
所以如果你想让 valudateURL 在这种情况下在非主线程中工作,你应该在没有 dispatch_async.
的情况下调用它
-- 已编辑 --
是的,所以 getUserProfile: 在主线程中阻止 运行s,如您在屏幕截图中所见,这就是它阻止应用程序的原因。所以如果你想在后台 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
});
}];
});
}];
}
我有一种方法可以在应用程序激活时检查剪贴板:
- (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 方法似乎不起作用。
这是我挂机时主线程的截图:
这是它挂起的函数:
- (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");
}
}];
}
似乎 checkClipboard 方法在主线程中调用了 valudateURL,像这样:
dispatch_async(dispatch_get_main_queue(), ^{
[self valudateURL];
});
所以如果你想让 valudateURL 在这种情况下在非主线程中工作,你应该在没有 dispatch_async.
的情况下调用它-- 已编辑 --
是的,所以 getUserProfile: 在主线程中阻止 运行s,如您在屏幕截图中所见,这就是它阻止应用程序的原因。所以如果你想在后台 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
});
}];
});
}];
}