2012-12-11 71 views
-1

我意識到這已被問了很多次,但我只是不知道錯誤在哪裏出現在我的代碼中,對於愚蠢而抱歉。集合<CALayerArray:0x1cdb9b90>在枚舉時發生了變化

我知道故障是由這種方法:

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

和IM呼籲在viewWillAppear中方法的方法...

[self performSelectorInBackground:@selector(getDataFromDatabase) withObject:nil];

任何提示,我的代碼可能是以次充好,任何幫助都非常感謝!

謝謝。

+1

這是很多代碼。你在哪裏迭代數組元素? –

+1

好吧,無論何時你使用UIKit方法進行交互(如上面添加和刪除子視圖),它必須在主線程上完成,而不是在後臺線程中完成,就像你在這裏做的那樣。 UIKit是**不是線程安全的! – lnafziger

回答

3

你在這裏有幾個問題,主要涉及修改後臺線程上的用戶界面,你絕對不能這樣做。例如:

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「搞定」了可可中的特殊含義)。如果視圖出現多次,你可以結束許多線程同時運行,這當然不是你的意思。

你應該幾乎從不使用performSelectorInBackground:withObject:。使用NSOperationQueue或分派隊列來管理後臺操作。

+0

我剛開始學習,太複雜了!你可以給我一些代碼示例,這樣我就可以玩了! – rjg

+0

還沒有線索從哪裏開始! – rjg

+0

我會開始簡單。我在上面的代碼中看不到任何需要後臺線程的東西。您可以在不產生線程的情況下進行大量的iOS開發。您的主要問題是您已將JSON網絡提取集成到視圖控制器中。不要這樣做。將數據提取放入只管理數據的模型類中(並使用NSURLConnection異步獲取數據)。然後視圖控制器將響應模型類的變化。請參閱http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MVC.html –

相關問題