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
}