主线程访问布局引擎后后台线程修改致Map加载崩溃求助
解决Tab Bar切换时MKMapView多次加载崩溃问题
崩溃报错:
Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
问题核心:你仅将弹窗逻辑切换到了主线程,但修改MKMapView的核心操作(设置区域、添加标注)仍在后台线程执行——NSURLConnection sendAsynchronousRequest使用了自定义的NSOperationQueue,其completionHandler会在这个后台队列运行,而UIKit组件(包括MKMapView)的所有操作必须在主线程执行。
修复方案
将所有涉及UI/地图修改的代码,包括设置地图区域、添加标注的逻辑,全部包裹到dispatch_async(dispatch_get_main_queue(), ^{ ... })块中,确保任何UI相关操作都不在后台线程执行。
修改后的代码
-(void)showGoMap{ // 若showGoMap在后台线程调用,这行也需移到主线程,避免潜在隐患 dispatch_async(dispatch_get_main_queue(), ^{ self.mapView.hidden = NO; }); int randomIndex = arc4random() % [arr_OfCountryCode count]; NSString *urlString = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false,+CA&key=MY_API_KEY", [arr_OfCountryCode objectAtIndex:randomIndex]]; NSURL *url = [[NSURL alloc] initWithString:urlString]; NSLog(@"Sending request"); [NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:url] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { NSLog(@"Response Received"); if (error) { NSLog(@"%@",error.description); return; } NSDictionary *jsonObject=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; NSLog(@"Data: %@", jsonObject); NSString *responseStatus = [[jsonObject objectForKey:@"status"] lowercaseString]; NSLog(@"Status: %@", responseStatus); if (![responseStatus isEqualToString:@"ok"]) { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertController *limitExceededAlert = [UIAlertController alertControllerWithTitle:@"Not working This Time!" message:@"Try Again" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"I'll Try Again Shortly" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { }]; [limitExceededAlert addAction:okAction]; [self presentViewController:limitExceededAlert animated:true completion:nil]; }); return; } NSDictionary *places = [[[[jsonObject objectForKey:@"results"] objectAtIndex:0] objectForKey:@"geometry"] objectForKey:@"location"]; NSDictionary *locations = [[[jsonObject objectForKey:@"results"] objectAtIndex:0] objectForKey:@"address_components"]; float lat = [[places objectForKey:@"lat"] floatValue]; float lon = [[places objectForKey:@"lng"] floatValue]; MKCoordinateRegion region; MKCoordinateSpan span; span.latitudeDelta = 0.50; span.longitudeDelta = 0.50; CLLocationCoordinate2D location = CLLocationCoordinate2DMake(lat, lon); region.span = span; region.center = location; NSString *str_Title = [[locations valueForKey:@"long_name"] objectAtIndex:0]; NSString *str_Short = [[locations valueForKey:@"short_name"] objectAtIndex:0]; MKPointAnnotation *point = [[MKPointAnnotation alloc] init]; point.coordinate = location; point.title = str_Title; point.subtitle = str_Short; // 所有地图相关操作移到主线程执行 dispatch_async(dispatch_get_main_queue(), ^{ [self.mk_MapView setRegion:region animated:YES]; [self.mk_MapView addAnnotation:point]; }); }]; }
内容的提问来源于stack exchange,提问作者DannyRoy
相关产品推荐
相关产品推荐

