【问题标题】:How to add row/cells dynamically to an UITableView by pressing a button in iPhone如何通过按下 iPhone 中的按钮将行/单元格动态添加到 UITableView
【发布时间】:2012-05-02 05:34:20
【问题描述】:

最初我有一个只有一个添加按钮的表格视图。

当用户按下此按钮时,我需要增加单元格计数并按如下方式添加单元格

如何编写行数以及如何通过单击添加按钮添加新行

//行数

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    return **????** ;
}

// 单元格/行上的内容

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
       ??????
}

// ### 添加新行.. ###

-(IBAction)myAction:(id)sender
{
    ???????? ;
}

提前谢谢...

【问题讨论】:

  • 基本上你不会将它们添加到视图中,而是添加到模型中。完成后,tableviews reloadData 方法就是你的朋友

标签: iphone objective-c uitableview


【解决方案1】:

UITableView 具有插入行或节的属性。见Apple Doc

这方面有很多教程。有 2 个常用来添加/删除行/节。

insertRowsAtIndexPaths:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:

我已经发布了类似的答案如何使用它: Hiding the table view cells with switch ON/OFF in iPhone

【讨论】:

【解决方案2】:

在您的应用程序中,当您在 btn 中执行操作时,您必须向 Array 添加值。

例如,在您的表格视图中,您在 cell.textLABEL.text 中显示 NSString。这些字符串在 NSMutableArray 中。

现在当 buttonAction 被调用时

我的行动

{
    NSString *newString =@"NEW CELL";

    [tableArray addObject:newString];
    [tableView reloadData];
}

在你的应用程序中尝试这个关于你的模态的逻辑。

我希望这个逻辑对你有帮助。

【讨论】:

  • 这会起作用,但会导致性能下降。添加一个新的单元格重新加载整个 UITableview 是没有意义的。
  • 同意纳文。改用 insertRowsAtIndexPaths
【解决方案3】:

每次要添加或删除行时重新加载表视图会给应用程序的用户带来糟糕的体验。尽管它不是执行此任务的有效方式,但它也有一些负面影响 - 重新加载后选定的行不会保持选中状态,并且更改没有动画。

UITableView 具有动态更改表格视图内容的方法。它们是:

insertRowsAtIndexPaths:withRowAnimation:
moveRowAtIndexPath:toIndexPath:
deleteRowsAtIndexPaths:withRowAnimation:

请注意,这些方法允许您指定执行指定操作时将使用的动画类型——当您使用reloadData 修改表格视图的内容时,您无法实现这种行为。

此外,您甚至可以使用表格视图的附加方法组合多个表格视图操作(这不是必需的):

开始更新 结束更新

只需将您要执行的操作包装到对beginUpdatesendUpdates 方法的调用中,表格视图将为beginUpdatesendUpdates 之间请求的所有操作创建一个 动画调用,以便整个过渡看起来比由几个单独的动画创建的过渡更好。

[self.tableView beginUpdates]
//calls to insert/move and delete methods   
[self.tableView endUpdates]

保持数据源状态与UITableView 保持一致非常重要。因此,您必须确保当表视图开始执行请求的操作时,其数据源将返回正确的值。

[self.tableView beginUpdates]
//calls to insert/move and delete methods   
//operations on our data source so that its
//state is consistent with state of the table view
[self.tableView endUpdates]

表视图何时开始执行操作?这取决于操作是否在beginUpdatesendUpdates 方法定义的动画块中。如果是,则表视图在endUpdates 方法调用后开始执行操作。否则,表格视图会在调用插入/移动或删除方法后立即执行操作。

当您使用beginUpdatesendUpdates 方法对表视图执行操作时,您必须知道在这种情况下表视图“批处理”请求的操作并以特定顺序执行它们,这与顺序不一定相同您对表格视图对象 (Apple's documentation on this topic) 进行的调用。

要记住的最重要的事情是删除所有操作总是在所有插入操作之前执行。此外,当插入操作按升序执行(索引 1、2、3 的操作)时,删除操作似乎按降序执行(索引 3、2、1 的操作)。请记住,这对于保持数据源的状态与表视图保持的状态保持一致至关重要

花一些时间来分析数据源和表视图的操作顺序,如下例所示。

最后一个例子:

//initial state of the data source
self.numbers = [@[@(0), @(1), @(2), @(3), @(4), @(5), @(6)] mutableCopy];
//
//...
//

NSArray indexPathsToRemove = @[[NSIndexPath indexPathForRow:3 section:0].
                               [NSIndexPath indexPathForRow:0 section:0];
NSArray indexPathsToAdd = @[[NSIndexPath indexPathForRow:6 section:0],
                            [NSIndexPath indexPathForRow:5 section:0]];

[self.tableView beginUpdates];

[self.numbers removeObjectAtIndex:3];
[self.numbers removeObjectAtIndex:0];

[self.numbers insertObject:@(10) atIndex:4];
[self.numbers insertObject:@(11) atIndex:5];

[self.tableView insertRowsAtIndexPaths:indexPathsToAdd withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView deleteRowsAtIndexPaths:indexPathsToRemove withRowAnimation:UITableViewRowAnimationAutomatic];

[self.tableView endUpdates];
//final state of the data source ('numbers') - 1, 2, 4, 5, 6, 10, 11

【讨论】:

    【解决方案4】:

    这里还有其他正确答案(您应该阅读它们,因为它们更深入),但是在阅读了我能找到的所有解决方案后,我为此苦苦挣扎了一个多星期,因为没有任何解决方案(我发现!)与全面的例子。

    执行此操作的规则: 1. 必须直接对包含您在UITableView 中显示的项目的数组进行更改。如果您在tableView:cellForRowAtIndexPath: 方法中将UITableViewCell 中的某个值设置为等于self.expandableArray 中的值,则必须self.expandableArray 进行更改,以使这些方法起作用。

    1. 对 tableView 中显示的项目数组的更改必须在两者之间进行 [tableView beginUpdates][tableView endUpdates]
    2. indexPaths 数组的计数必须等于您添加到 tableView 的其他项目的计数(我认为这很明显,但指出这一点并没有什么坏处)

    这是一个非常简单的示例,可以单独运行。

        @interface MyTableViewController ()
    @property (nonatomic, strong) NSMutableArray *expandableArray;
    @property (nonatomic, strong) NSMutableArray *indexPaths;
    @property (nonatomic, strong) UITableView *myTableView;
    @end
    
    @implementation MyTableViewController
    
    - (void)viewDidLoad
    {
        [self setupArray];
    }
    
    - (void)setupArray
    {
        self.expandableArray = @[@"One", @"Two", @"Three", @"Four", @"Five"].mutableCopy;
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return self.expandableArray.count;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //here you should create a cell that displays information from self.expandableArray, and return it
    }
    
    //call this method if your button/cell/whatever is tapped
    - (void)didTapTriggerToChangeTableView
    {
        if (/*some condition occurs that makes you want to expand the tableView*/) {
            [self expandArray]
        }else if (/*some other condition occurs that makes you want to retract the tableView*/){
            [self retractArray]
        }
    }
    
    //this example adds 1 item
    - (void)expandArray
    {
        //create an array of indexPaths
        self.indexPaths = [[NSMutableArray alloc] init];
        for (int i = theFirstIndexWhereYouWantToInsertYourAdditionalCells; i < theTotalNumberOfAdditionalCellsToInsert + theFirstIndexWhereYouWantToInsertYourAdditionalCells; i++) {
            [self.indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]];
        }
    
        //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
        [self.myTableView beginUpdates];
        //HERE IS WHERE YOU NEED TO ALTER self.expandableArray to have the additional/new data values, eg:
        [self.expandableArray addObject:@"Six"];
        [self.myTableView insertRowsAtIndexPaths:self.indexPaths withRowAnimation:(UITableViewRowAnimationFade)];  //or a rowAnimation of your choice
    
        [self.myTableView endUpdates];
    }
    
    //this example removes all but the first 3 items
    - (void)retractArray
    {
        NSRange range;
        range.location = 3;
        range.length = self.expandableArray.count - 3;
    
        //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates
        [self.myTableView beginUpdates];
        [self.expandableArray removeObjectsInRange:range];
        [self.myTableView deleteRowsAtIndexPaths:self.indexPaths withRowAnimation:UITableViewRowAnimationFade];  //or a rowAnimation of your choice
        [self.myTableView endUpdates];
    }
    
    @end
    

    我希望这可以节省很多人的时间和头痛。如果你这样做,你不需要重新加载整个 tableView 来更新它,你可以为它选择一个动画。免费代码,不要敲它。

    【讨论】:

    • 我有类似的情况。我有 76 个对象的数组(大约)。在填充 tableview 时,table 一次只能显示 10 个单元格。首先 0-10 个对象,然后按下下一个按钮表应该显示 11-20 数据,然后是 21-30 等等......所以我怎么能这样做呢?你对此有什么想法吗?
    【解决方案5】:

    您可以在数组中添加对象并在单击按钮时重新加载您的表格视图。

    [array addobject:@""];
    [tableview reloaddata];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 2015-07-29
      • 1970-01-01
      • 2015-02-10
      • 1970-01-01
      相关资源
      最近更新 更多