Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/111.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 异步改变子视图_Ios_Objective C - Fatal编程技术网

Ios 异步改变子视图

Ios 异步改变子视图,ios,objective-c,Ios,Objective C,在后台添加和删除视图时出现问题 我尝试了[self-performSelectorInBackground:@selector(loadDataInScrollView),对象为nil] 及 每次我得到集合时,在枚举时都会发生变异。“ 代码: - (void)loadDataInScrollView { int thresholdStart = currentPage * numberOfElementsPerLine - (numberOfPreloadedPages / 2) *

在后台添加和删除视图时出现问题

我尝试了
[self-performSelectorInBackground:@selector(loadDataInScrollView),对象为nil]

每次我得到
集合时,在枚举时都会发生变异。“

代码:

- (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
}
-(void)loadDataInScrollView{
int thresholdStart=currentPage*numberOfElementsPerLine-(NumberOfPreviedPages/2)*numberOfElementsPerLine;
int start=thresholdStart>0?thresholdStart:0;
int thresholdEnd=currentPage*numberOfElementsPerLine+numberOfVisibleElements+(NumberOfPreviedPages/2)*numberOfElementsPerLine;
int end=thresholdEnd>numberOfElements?numberOfElements:thresholdEnd;
for(int i=start;ibase.contentOffset.y?底部:顶部;
[self-loadDataInScrollView];//在这里,我尝试了不同的方式在后台发送
}

错误消息会告诉您问题所在以及如何处理。在枚举该数组(即for循环的中间)时,不能对可变数组进行突变。您需要遍历数组,并为要更改的内容创建一个单独的不可更改列表(数组)。循环完全结束后,在使用该列表进行更改的地方执行另一个循环

此外,您决不能触摸后台线程中的界面。您正在后台调用
loadDataInScrollView
。因此,
loadDataInScrollView
在后台调用
removeElementAtIndex
。因此,
removeementatindex
在后台调用
removeFromSuperview
,这是完全非法的


因此,基于这两个原因,您必须完全重新构建您的方法。

我知道我不允许在后台触摸界面。。但这是一项繁重的工作,而且滚动时移动速度很慢。。你知道怎么做吗?我不知道你想做什么,所以不。你不应该在滚动时做任何“繁重的工作”,正是因为这个原因。过去有很多很棒的WWDC视频讨论如何高效滚动;你可以看一些。另外,使用仪器准确地告诉你是什么导致帧速率变慢。马特的两个分数都是+1。永远不要在枚举集合时对其进行变异,在任何情况下都不要从后台线程操纵UI。如果需要,可以使用诸如performSelectorOnMainThread或类似GCD调用之类的代码从后台线程对主线程进行UI调用。
- (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
}