在创建表格视图单元之前删除数组中的元素

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 在 vi​​ewDidLoad 中没有改变。也不在 viewWillAppear 方法中。如果我将代码放在 viewDidAppear 中,它可以工作,但整个列表在加载前会显示一小段时间。我错过了什么特别的事情吗?我想我应该使用 viewWillAppear 方法? 您从哪里获得列表的数据?为什么要在实际显示表格之后和之前对其进行操作。【参考方案2】:

您可以使用这种方法:

免责声明 - 这完全是伪智囊,它也是在没有 IDE 的情况下编写的。所以它有可能根本无法工作或编译。

animalTableViewControllerviewDidLoad() 内,您可以执行以下操作:

-(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。我的手拍在我的额头上

以上是关于在创建表格视图单元之前删除数组中的元素的主要内容,如果未能解决你的问题,请参考以下文章

python怎么操作多维数组元素

如何将表格视图数组中的每个字符串分隔到自己的单元格中?

专门更改填充了数组元素的表格视图中的一个单元格

表格视图中的警告

创建“实时”表视图的最佳方法

如何在iOS中的表视图底部创建固定单元格?