如何通过按下iPhone中的按钮动态地将行/单元格添加到UITableView

时间:2023-01-19 16:58:35

Initially i have a table view with only one add button.

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

when user press this button i need to increment the cells count and add the cells as follows

当用户按下此按钮时,我需要递增细胞计数并按如下方式添加细胞

How to write row count and how to add new rows by click on the add button

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

//Row count

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

// Content on cells/rows

//单元格/行上的内容

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

// ### Add New Row.. ###

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

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

Thanks in advance...

提前致谢...

5 个解决方案

#1


7  

In your application You have to add values to Array when you performing action in btn.

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

For example in your tableview you are displaying NSString in cell.textLABEL.text. These strings are in NSMutableArray.

例如,在tableview中,您将在cell.textLABEL.text中显示NSString。这些字符串在NSMutableArray中。

Now when buttonAction is called

现在调用buttonAction时

in myAction

{
    NSString *newString =@"NEW CELL";

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

Try this logic in your application regarding to your modal.

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

I hope this logic will be helpful to you.

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

#2


11  

UITableView has property to insert row or section. see Apple Doc

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

There are many tutorial on this. there are 2 commonly use to add/delete row/section.

这方面有很多教程。有2个常用于添加/删除行/部分。

insertRowsAtIndexPaths:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:

I have posted similar answer how to use this : Hiding the table view cells with switch ON/OFF in iPhone

我已经发布了类似的答案如何使用它:在iPhone中用开关ON / OFF隐藏表格查看单元格

#3


7  

Reloading of the table view each time you want to add or remove row creates poor experience for the user of your application. Despite the fact it isn’t efficient way to perform this task it also has some negative side effects - selected rows don’t stay selected after reload and change isn’t animated.

每次要添加或删除行时重新加载表视图都会给应用程序用户带来不良体验。尽管它不是执行此任务的有效方法,但它也有一些负面的副作用 - 选择的行在重新加载后不会保持选中状态并且不会对更改进行动画处理。

UITableView has methods which were created to change content of the table view dynamically. These are:

UITableView具有创建的方法,可以动态更改表视图的内容。这些是:

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

Notice that these methods allow you to specify kind of animation which will be used when specified operation is performed - you cannot achieve this kind of behavior when you use reloadData to modify the content of the table view.

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

Moreover, you can even combine multiple table view operations using additional methods of the table view (this is not necessary):

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

beginUpdates endUpdates

Just wrap operations you want to perform into calls to beginUpdates and endUpdates methods and table view will create one animation for all operations that have been requested between beginUpdates and endUpdates calls so that whole transition looks nicer that one created by a few separated animations.

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

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

It is really important to keep you data source state consistent with the one kept by UITableView. For this reason you must assure that when table view starts to perform requested operations its data source will return correct values.

保持数据源状态与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]

When table view start performing operations? This depends on whether operations are being in animation block defined by beginUpdates and endUpdates methods. If yes, table view starts to perform operations after endUpdates method call. Otherwise, table view performs operations just after call to insert/move or delete method has been made.

当表视图开始执行操作时?这取决于操作是否在由beginUpdates和endUpdates方法定义的动画块中。如果是,则表视图在endUpdates方法调用之后开始执行操作。否则,表视图在调用insert / move或delete方法之后立即执行操作。

When you are using beginUpdates and endUpdates methods to perform operations on table view you have to know that in this case table view ‚batches’ requested operations and performs them in specific order which is not necessary the same as order of the calls you made on your table view object (Apple's documentation on this topic).

当您使用beginUpdates和endUpdates方法对表视图执行操作时,您必须知道在这种情况下表视图,批处理所请求的操作并按特定顺序执行它们,这与您在您的调用中所做的调用顺序不一定相同。表视图对象(Apple关于此主题的文档)。

The most important thing to remember is that deletion all operations are always performed before all insertion operations. Also, deletion operations seems to be performed in descending order (operations for indexes 3, 2, 1) when insertion operation are performed in ascending order (operations for indexes 1, 2, 3). Remember about this is crucial in keeping state of your data source consistent with the one kept by table view.

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

Spend some time on analyzing order of the operations on data source and table view in presented in example below.

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

Final example:

//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


2  

There are other correct answers here (which you should read because they go further in-depth), but I struggled for over a week with this after reading all the solutions I could find because there weren't any (that I found!) with comprehensive examples.

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

Rules for this to work: 1. Changes must be made directly to the array that contains the items you're displaying in the UITableView. If you set some value in a UITableViewCell in the tableView:cellForRowAtIndexPath: method to equal values in self.expandableArray, then changes must also be made to self.expandableArray in order for these methods to work.

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

  1. changes to the array of items that are displayed in the tableView must be made in-between [tableView beginUpdates] and [tableView endUpdates]
  2. 必须在[tableView beginUpdates]和[tableView endUpdates]之间更改tableView中显示的项目数组

  3. The count of the indexPaths array must equal the count of the additional items you're adding to the tableView (I think that's obvious, but it doesn't hurt to point that out)
  4. indexPaths数组的计数必须等于你要添加到tableView的附加项的计数(我认为这很明显,但指出这一点并没有坏处)

here is a very simple example that would work on its own.

这是一个非常简单的例子,它可以独立工作。

    @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

I hope this saves someone a lot of time and headache. If you do it this way, you don't need to reload the whole tableView to update it, and you're able to select an animation for it. Free code, don't knock it.

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

#5


0  

You can just add object in array and reload your tableview on button click.

您只需在数组中添加对象,然后在按钮单击时重新加载您的tableview。

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

#1


7  

In your application You have to add values to Array when you performing action in btn.

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

For example in your tableview you are displaying NSString in cell.textLABEL.text. These strings are in NSMutableArray.

例如,在tableview中,您将在cell.textLABEL.text中显示NSString。这些字符串在NSMutableArray中。

Now when buttonAction is called

现在调用buttonAction时

in myAction

{
    NSString *newString =@"NEW CELL";

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

Try this logic in your application regarding to your modal.

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

I hope this logic will be helpful to you.

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

#2


11  

UITableView has property to insert row or section. see Apple Doc

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

There are many tutorial on this. there are 2 commonly use to add/delete row/section.

这方面有很多教程。有2个常用于添加/删除行/部分。

insertRowsAtIndexPaths:withRowAnimation:
deleteRowsAtIndexPaths:withRowAnimation:

I have posted similar answer how to use this : Hiding the table view cells with switch ON/OFF in iPhone

我已经发布了类似的答案如何使用它:在iPhone中用开关ON / OFF隐藏表格查看单元格

#3


7  

Reloading of the table view each time you want to add or remove row creates poor experience for the user of your application. Despite the fact it isn’t efficient way to perform this task it also has some negative side effects - selected rows don’t stay selected after reload and change isn’t animated.

每次要添加或删除行时重新加载表视图都会给应用程序用户带来不良体验。尽管它不是执行此任务的有效方法,但它也有一些负面的副作用 - 选择的行在重新加载后不会保持选中状态并且不会对更改进行动画处理。

UITableView has methods which were created to change content of the table view dynamically. These are:

UITableView具有创建的方法,可以动态更改表视图的内容。这些是:

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

Notice that these methods allow you to specify kind of animation which will be used when specified operation is performed - you cannot achieve this kind of behavior when you use reloadData to modify the content of the table view.

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

Moreover, you can even combine multiple table view operations using additional methods of the table view (this is not necessary):

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

beginUpdates endUpdates

Just wrap operations you want to perform into calls to beginUpdates and endUpdates methods and table view will create one animation for all operations that have been requested between beginUpdates and endUpdates calls so that whole transition looks nicer that one created by a few separated animations.

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

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

It is really important to keep you data source state consistent with the one kept by UITableView. For this reason you must assure that when table view starts to perform requested operations its data source will return correct values.

保持数据源状态与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]

When table view start performing operations? This depends on whether operations are being in animation block defined by beginUpdates and endUpdates methods. If yes, table view starts to perform operations after endUpdates method call. Otherwise, table view performs operations just after call to insert/move or delete method has been made.

当表视图开始执行操作时?这取决于操作是否在由beginUpdates和endUpdates方法定义的动画块中。如果是,则表视图在endUpdates方法调用之后开始执行操作。否则,表视图在调用insert / move或delete方法之后立即执行操作。

When you are using beginUpdates and endUpdates methods to perform operations on table view you have to know that in this case table view ‚batches’ requested operations and performs them in specific order which is not necessary the same as order of the calls you made on your table view object (Apple's documentation on this topic).

当您使用beginUpdates和endUpdates方法对表视图执行操作时,您必须知道在这种情况下表视图,批处理所请求的操作并按特定顺序执行它们,这与您在您的调用中所做的调用顺序不一定相同。表视图对象(Apple关于此主题的文档)。

The most important thing to remember is that deletion all operations are always performed before all insertion operations. Also, deletion operations seems to be performed in descending order (operations for indexes 3, 2, 1) when insertion operation are performed in ascending order (operations for indexes 1, 2, 3). Remember about this is crucial in keeping state of your data source consistent with the one kept by table view.

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

Spend some time on analyzing order of the operations on data source and table view in presented in example below.

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

Final example:

//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


2  

There are other correct answers here (which you should read because they go further in-depth), but I struggled for over a week with this after reading all the solutions I could find because there weren't any (that I found!) with comprehensive examples.

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

Rules for this to work: 1. Changes must be made directly to the array that contains the items you're displaying in the UITableView. If you set some value in a UITableViewCell in the tableView:cellForRowAtIndexPath: method to equal values in self.expandableArray, then changes must also be made to self.expandableArray in order for these methods to work.

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

  1. changes to the array of items that are displayed in the tableView must be made in-between [tableView beginUpdates] and [tableView endUpdates]
  2. 必须在[tableView beginUpdates]和[tableView endUpdates]之间更改tableView中显示的项目数组

  3. The count of the indexPaths array must equal the count of the additional items you're adding to the tableView (I think that's obvious, but it doesn't hurt to point that out)
  4. indexPaths数组的计数必须等于你要添加到tableView的附加项的计数(我认为这很明显,但指出这一点并没有坏处)

here is a very simple example that would work on its own.

这是一个非常简单的例子,它可以独立工作。

    @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

I hope this saves someone a lot of time and headache. If you do it this way, you don't need to reload the whole tableView to update it, and you're able to select an animation for it. Free code, don't knock it.

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

#5


0  

You can just add object in array and reload your tableview on button click.

您只需在数组中添加对象,然后在按钮单击时重新加载您的tableview。

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