我意识到这已被多次询问,但我只是不知道我的代码中的错误在哪里,抱歉愚蠢。
我知道错误来自这个方法:
-(void)getDataFromDatabase {
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
indicator.center = self.view.center;
[indicator bringSubviewToFront:self.view];
[UIApplication sharedApplication].networkActivityIndicatorVisible = TRUE;
[indicator startAnimating];
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIView *overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, screenRect.size.width, screenRect.size.height)];
overlay.backgroundColor = [UIColor whiteColor];
[self.view addSubview:overlay];
[self.view addSubview:indicator];
NSString *listingurl;
listingurl = [NSString stringWithFormat:@"http://www.herefordshire-tourism-guide.co.uk/app/query.php?getlisting=1&listingname=%@", rowSelectedName];
listingurl = [listingurl stringByReplacingOccurrencesOfString:@" " withString:@"%20"];
NSURL *url = [NSURL URLWithString:listingurl];
NSError *error = nil;
NSStringEncoding encoding;
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url usedEncoding:&encoding
error:&error];
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = dict[@"listings"];
}
dict = rows[0];
self.photos.font = [UIFont fontWithName:@"ProximaNova-Regular" size:18.0];
self.likes.font = [UIFont fontWithName:@"ProximaNova-Regular" size:18.0];
self.businessName.font = [UIFont fontWithName:@"ProximaNova-Extrabld" size:20.0];
self.address.font = [UIFont fontWithName:@"ProximaNova-Regular" size:16.0];
self.navigationItem.title = dict[@"business"];
NSString *favdb = [NSString stringWithFormat:@"%@", dict[@"favs"]];
if ([favdb isEqualToString:@""]) {
NSString *fav = [NSString stringWithFormat:@"0 Likes"];
self.favourites.text = fav;
} else {
NSString *fav = [NSString stringWithFormat:@"%@ Likes", dict[@"favs"]];
self.favourites.text = fav;
}
if ([favdb isEqualToString:@"1"]) {
NSString *fav = [NSString stringWithFormat:@"1 Like"];
self.favourites.text = fav;
}
self.businessName.text = dict[@"business"];
self.address.text = dict[@"location"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.frame = CGRectMake(140, 85, 40.0, 40.0);
[indicator bringSubviewToFront:self.view];
[indicator startAnimating];
[self.view addSubview:indicator];
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:dict[@"image1"]]]];
self.image.image = img;
[UIApplication sharedApplication].networkActivityIndicatorVisible = FALSE;
[indicator stopAnimating];
});
listingLoc = [[CLLocation alloc] initWithLatitude:[dict[@"lat"] doubleValue] longitude:[dict[@"lon"] doubleValue]];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
float kilometers = [appDelegate.currentLoc distanceFromLocation:listingLoc] / 1000;
int milesint = kilometers * 0.621371192;
NSString *milesOut = [NSString stringWithFormat:@"%i miles", milesint];
self.distance.text = milesOut;
networkImages = [[NSMutableArray alloc] init];
if (dict[@"image1"] != @"") {
[networkImages addObject:dict[@"image1"]];
}
[indicator stopAnimating];
[overlay removeFromSuperview];
}
我在viewWillAppear方法中调用该方法......
[self performSelectorInBackground:@selector(getDataFromDatabase) withObject:nil];
任何提示,我的代码可能有点粗制滥造,非常感谢任何帮助!
感谢。
答案 0 :(得分:3)
你在这里遇到了几个问题,主要与在后台线程上修改UI有关,你绝对不能这样做。例如:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
indicator.frame = CGRectMake(140, 85, 40.0, 40.0);
[indicator bringSubviewToFront:self.view];
[indicator startAnimating];
[self.view addSubview:indicator];
...
您可以在此处修改当前视图在后台线程上的子视图列表。那不合法。大多数UIKit方法必须在主线程上运行(从GCD的角度来看,这是主队列)。
此行在viewWillAppear:
(或大多数地方)内部也非常危险:
[self performSelectorInBackground:@selector(getDataFromDatabase) withObject:nil];
您的观点可能会在getDataFromDatabase
期间多次出现和消失(旁注:您应该调用此fetchDataFromDatabase
。" get"在Cocoa中具有特殊含义)。如果视图出现多次,你可以结束同时运行的许多线程,这肯定不是你的意思。
你几乎不应该使用performSelectorInBackground:withObject:
。使用NSOperationQueue
或调度队列来管理后台操作。