收集<calayerarray:0x1cdb9b90 =“”>在被枚举时被突变</calayerarray:>

时间:2012-12-11 17:31:41

标签: objective-c ios

我意识到这已被多次询问,但我只是不知道我的代码中的错误在哪里,抱歉愚蠢。

我知道错误来自这个方法:

-(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];

任何提示,我的代码可能有点粗制滥造,非常感谢任何帮助!

感谢。

1 个答案:

答案 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。&#34; get&#34;在Cocoa中具有特殊含义)。如果视图出现多次,你可以结束同时运行的许多线程,这肯定不是你的意思。

你几乎不应该使用performSelectorInBackground:withObject:。使用NSOperationQueue或调度队列来管理后台操作。