在创建表格视图单元之前删除数组中的元素
Posted
技术标签:
【中文标题】在创建表格视图单元之前删除数组中的元素【英文标题】:Delete element in array before creating table view cells 【发布时间】:2013-06-26 12:33:57 【问题描述】:我是 Objective-c 的新手,我正在尝试做一个 UItableview 应用程序。整个概念是我有两个视图,两个表视图。在第一个视图控制器中,我有几个月,根据您按下的月份,我在第二个视图控制器中更改整数(int currentMonth)。在第二个视图控制器中,我想展示一个带有动物的表格视图。这些动物应该只显示它们是否“可猎”,并且还应显示它们“可猎”多长时间,并且我已经为此编写了代码并且它可以工作。
问题在于,我当前的代码从 animalArray 中删除对象并重新加载 cellForRowAtIndexPath 中 tableview 的数据,这使得滚动非常慢。
我试图提出其他解决方案,但到目前为止没有运气,所以我希望有人能把我推向正确的方向。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"DjurCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//skapar en variabel av Appdelegate för att komma åt arrayen med djur.
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
UIImage *background = [self cellBackgroundForRowAtIndexPath:indexPath];
UIImageView *cellBackgroundView = [[UIImageView alloc] initWithImage:background];
cellBackgroundView.image = background;
cell.backgroundView = cellBackgroundView;
if (cell== nil)
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//Skapar en label och länkar den med storyboard.
UILabel *animalNameLabel = (UILabel *)[cell viewWithTag:104];
UILabel *animalDetailLabel = (UILabel *)[cell viewWithTag:102];
NSString *strmonth;
switch (self.currentMonth)
case 0:
strmonth=@"Juli";
break;
case 1:
strmonth=@"Augusti";
break;
case 2:
strmonth=@"September";
break;
case 3:
strmonth=@"Oktober";
break;
case 4:
strmonth=@"November";
break;
case 5:
strmonth=@"December";
break;
case 6:
strmonth=@"Januari";
break;
case 7:
strmonth=@"Februari";
break;
case 8:
strmonth=@"Mars";
break;
case 9:
strmonth=@"April";
break;
case 10:
strmonth=@"Maj";
break;
case 11:
strmonth=@"Juni";
break;
case 12:
strmonth=@"Juli";
break;
default:
break;
//Algoritm för utskrivandet av hur lång tid en art är jaktbar. Om nuvarande månad är större än jaktstarten och mindre än jaktstoppet.
if ((self.currentMonth>[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstartmonth])&&(self.currentMonth<[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstopmonth]))
animalNameLabel.text = [[appDelegate.animalArray objectAtIndex:indexPath.row]getArt];
animalDetailLabel.text = @"Jaktbar hela månaden";
//Om nuvarande månad är lika med jaktstarten.
else if(self.currentMonth==[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstartmonth])
animalNameLabel.text = [[appDelegate.animalArray objectAtIndex:indexPath.row]getArt];
animalDetailLabel.text = [NSString stringWithFormat:@"Jaktbar från och med den %i:e %@",[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstartday],strmonth];
//Om nuvarande månad är lika med jaktstoppet.
else if(self.currentMonth==[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstopmonth])
animalNameLabel.text = [[appDelegate.animalArray objectAtIndex:indexPath.row]getArt];
animalDetailLabel.text = [NSString stringWithFormat:@"Jaktbar till och med den %i:e %@",[[appDelegate.animalArray objectAtIndex:indexPath.row]getjaktstopday],strmonth];
//I övriga fall
else
animalNameLabel.text = [[appDelegate.animalArray objectAtIndex:indexPath.row]getArt];
animalDetailLabel.text = [NSString stringWithFormat:@"Ej Jaktbar"];
//这就是滚动缓慢的原因。
if ([animalDetailLabel.text isEqual:@"Ej Jaktbar"])
[appDelegate.animalArray removeObjectAtIndex:indexPath.row];
[tableView reloadData];
return cell;
任何想法我应该如何更改代码?
【问题讨论】:
【参考方案1】:切勿从 cellForRowAtIndexPath 中调用重新加载数据。 这样做的目的是什么?
我认为从该数组中删除一个“驱动”表内容的字段不是一个好主意。您可以在不重新加载数据的情况下执行此操作,但您必须期望该表会请求您在数组中没有相应索引的单元格。
但是,当您以更合适的方法(viewDidLoad?)更改数据时,您的情况会好得多。您可以强制表从重新加载过程未调用的任何方法重新加载其数据。由于重新加载,所有数据源方法都被调用。
如果您的代码稍有不同,那么您将面临无限循环的风险。在您的情况下,它不是无限的,因为您只需从数组中删除所有出现的“Ej Jaktbar”,这是有限的。但是对于每次出现,您都会一次又一次地重新加载表格。 cellForRorAtIndexPath 将从单元格 0 开始一次又一次地调用。但是您的表没有机会释放未使用的单元格。我猜你甚至会为你从未实际使用过的单元格视图占用大量内存。
【讨论】:
我同意,从cellForRowAtIndexPath:
中调用 reloadData 可能会导致在实际数据出现之前重新加载 x 次。这会大大减慢内容的呈现速度。
感谢您的回答。我尝试在 viewDidLoad 方法中对数组进行更改,但没有成功。在我的第一个视图中,来自 didSelectRowAtIndexpath 方法的月份标识符 currentMonth 在 viewDidLoad 中没有改变。也不在 viewWillAppear 方法中。如果我将代码放在 viewDidAppear 中,它可以工作,但整个列表在加载前会显示一小段时间。我错过了什么特别的事情吗?我想我应该使用 viewWillAppear 方法?
您从哪里获得列表的数据?为什么要在实际显示表格之后和之前对其进行操作。【参考方案2】:
您可以使用这种方法:
免责声明 - 这完全是伪智囊,它也是在没有 IDE 的情况下编写的。所以它有可能根本无法工作或编译。
在animalTableViewController
的viewDidLoad()
内,您可以执行以下操作:
-(void)viewDidLoad
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// it would be nice to get the month here. You could probably get it from a custom init of the viewController.
[appDelegate removeNonHuntableAnimalsFromDatasourceWithMonth:self.Month];
// the rest of your code
AppDelegate 中的函数可能看起来像这样:
从您的案例中可以看出,这取决于它是哪个月份,因此您可能需要在此处获取当前月份。可以从viewDidLoad
发送到您的animalViewController
-(void)removeNonHuntableAnimalsFromDatasourceWithMonth:(NSString *)month
// iterate through all animals
for (animalObject *animal in self.animalArray)
// if the month is lesser than the start or greater than the stop.
// calling [property intValue] can be done if the properties are of the type NSString
if ([month intValue] < [animal.jaktStart intValue] || [month.intValue] > [animal.jaktStopp intValue])
// remove the animal from the datasource
[self.animalArray removeObject:animal];
如果结构看起来像下面这样:
animalArray[0] = [AnimalObject]
(jaktStart) = 5
(jaktStopp) = 6
(art) = Duck
animalArray[1] = [AnimalObject]
(jaktStart) = 1
(jaktStopp) = 8
(art) = Moose
animalArray[2] = [AnimalObject]
(jaktStart) = 11
(jaktStopp) = 12
(art) = Wolf
animalArray[3] = [AnimalObject]
(jaktStart) = 2
(jaktStopp) = 4
(art) = Polarbear
因此,如果您的数据源看起来像上述结构,则循环将在第 11 个月将结构修改为以下结构。
animalArray[0] = [AnimalObject]
(jaktStart) = 11
(jaktStopp) = 12
(art) = Wolf
免责声明此代码可能会或可能根本不起作用!希望它能给你一些想法。
【讨论】:
谢谢@Da_smokes .. 我休息了一个星期,然后又跳回去了.. 问题解决了.. 我在第一个视图控制器中发现了问题。在 pushViewController 调用之前我没有设置 currentMonth。我的手拍在我的额头上以上是关于在创建表格视图单元之前删除数组中的元素的主要内容,如果未能解决你的问题,请参考以下文章