2014-10-04 90 views
0

我在添加和刪除後臺視圖時遇到問題。異步子視圖異步

我試圖[self performSelectorInBackground:@selector(loadDataInScrollView) withObject:nil];

而且

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
    //Background Thread 
    dispatch_async(dispatch_get_main_queue(), ^(void){ 
     //Run UI Updates 
    }); 
}); 

每次我得到Collection <CALayerArray: 0x165a7e50> was mutated while being enumerated.'

代碼:

- (void)loadDataInScrollView { 

    int thresholdStart = currentPage * numberOfElementsPerLine - (numberOfPreloadedPages/2) * numberOfElementsPerLine; 
    int start = thresholdStart > 0 ? thresholdStart : 0; 

    int thresholdEnd = currentPage * numberOfElementsPerLine + numberOfVisibleElements + (numberOfPreloadedPages/2) * numberOfElementsPerLine; 
    int end = thresholdEnd > numberOfElements ? numberOfElements : thresholdEnd; 



    for (int i = start; i < end; i++) { 

     [self createElementAtIndex:i]; 
//   [self performSelectorInBackground:@selector(createElementAtIndex:) withObject:[NSNumber numberWithInt:i]]; 

     for (int i = TAG_CONFLICT; i < start + TAG_CONFLICT; i++) { 
      [self removeElementAtIndex:i]; 
     } 
     for (int i = end + TAG_CONFLICT; i < numberOfElements + TAG_CONFLICT; i++) { 
      [self removeElementAtIndex:i]; 
     } 

    } 


    self.isLoaded = YES; 

    NSLog(@"start: %d, end: %d", start, end); 
} 

- (void)removeElementAtIndex:(int)index { 

    UIView *view = [base viewWithTag:index]; 
    if (view != nil && ![view isKindOfClass:[UIImageView class]]) { 
     [view removeFromSuperview]; 
    } 

} 

- (void)createElementAtIndex:(int)index { 

    if (![base viewWithTag:index+TAG_CONFLICT]) { 
     int x = leftRightPadding + index % numberOfElementsPerLine * (sizeElement.width + flexibleSpace); 
     int y = topBottomPadding + index/numberOfElementsPerLine * (sizeElement.height + flexibleSpace); 
     UIView *element = [[UIView alloc] initWithFrame:CGRectMake(x, y, sizeElement.width, sizeElement.height)]; 
     [self.dataSource gallery:self view:element atIndex:index]; 

     if (border) { 
      element.layer.borderWidth = 1.0; 
      element.layer.borderColor = [borderColor CGColor]; 
     } 

     element.layer.masksToBounds = YES; 

     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(elementTapped:)]; 
     tap.numberOfTapsRequired = 1; 

     [element addGestureRecognizer:tap]; 

     [element setTag:index+TAG_CONFLICT]; 
     [element setAlpha:0]; 

     [base addSubview:element]; 

     [UIView animateWithDuration:0.3 animations:^{ 
      element.alpha = 1; 
     }]; 
    } 
} 

#pragma mark - ScrollView delegates 

- (void)scrollViewDidScroll:(UIScrollView *)scrollView { 

    initialOffset = scrollView.contentOffset.y; 
    currentPage = (initialOffset - topBottomPadding)/(sizeElement.height + topBottomPadding); 
    direction = initialOffset > base.contentOffset.y ? BOTTOM : TOP; 

    [self loadDataInScrollView]; // Here i've tried different ways to send in background 
} 

回答

1

錯誤消息告訴你的問題是什麼,做些什麼。枚舉該數組(即,在for循環的中間)時,不能改變可變數組。您需要遍歷數組,然後單獨製作您想要更改的事物的不可變列表(數組)。循環完成後,執行另一個循環,您可以使用該列表進行更改。

此外,您不得在後臺線程中觸摸該接口。您在後臺撥打loadDataInScrollView。因此loadDataInScrollView在後臺調用removeElementAtIndex。因此removeElementAtIndex在後臺調用removeFromSuperview - 這是完全非法的。

所以你將不得不在這兩個方面完全重新設計你的方法。

+0

我知道我不允許觸摸背景中的界面..但它是一項沉重的工作,它滾動時移動緩慢..你有什麼ideea如何做到這一點? – 2014-10-04 14:29:13

+0

我不知道你在做什麼,所以沒有。正因爲這個原因,你不應該在滾動的時候做任何「沉重的工作」。過去有很多偉大的WWDC視頻討論如何高效滾動;你可能會看一些。此外,請使用「樂器」來準確告訴您造成慢幀速率的原因。 – matt 2014-10-04 14:54:00

+0

這兩個馬特的觀點。枚舉時不要改變集合,並且在任何情況下都不要從後臺線程操縱UI。如果需要,您可以使用諸如performSelectorOnMainThread或類似GCD調用之類的代碼從後臺線程對主線程進行UI調用。 – 2014-10-04 15:01:50