ios “尝试将第 0 行插入第 0 节,但更新后第 0 节中只有 0 行”错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17005635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
"Attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update" Error
提问by Dan Grueneberg
I have an app that is selecting a person from their contacts list and takes their First name, last name and email. It then saves the first name to a nsmutablearray and puts it into a uitableview cell. My problem occurs once the contact is selected in the simulator.
我有一个应用程序,它从联系人列表中选择一个人并获取他们的名字、姓氏和电子邮件。然后将名字保存到 nsmutablearray 并将其放入 uitableview 单元格中。一旦在模拟器中选择了联系人,我的问题就会出现。
Code:
代码:
.h:
。H:
#import <UIKit/UIKit.h>
#import <AddressBookUI/AddressBookUI.h>
@interface FirstViewController : UIViewController < ABPeoplePickerNavigationControllerDelegate, UITableViewDelegate, UITableViewDataSource>
- (IBAction)showPicker:(id)sender;
@property (weak, nonatomic) IBOutlet NSString *firstName;
@property (weak, nonatomic) IBOutlet NSString *email;
@property (weak, nonatomic) IBOutlet NSString *lastName;
@property (weak, nonatomic) IBOutlet UITableView *myTableView;
@property (strong, nonatomic) NSMutableArray *contacts;
@end
.m:
.m:
#import "FirstViewController.h"
@interface FirstViewController ()
@end
@implementation FirstViewController
@synthesize firstName;
@synthesize email;
@synthesize lastName;
@synthesize contacts;
@synthesize myTableView;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
contacts = [[NSMutableArray alloc]initWithObjects:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView Datasource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return contacts.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [contacts objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)showPicker:(id)sender {
ABPeoplePickerNavigationController *picker =
[[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentModalViewController:picker animated:YES];
}
- (void)peoplePickerNavigationControllerDidCancel:
(ABPeoplePickerNavigationController *)peoplePicker
{
[self dismissModalViewControllerAnimated:YES];
}
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self displayPerson:person];
[self dismissModalViewControllerAnimated:YES];
return NO;
}
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
return NO;
}
- (void)displayPerson:(ABRecordRef)person
{
NSString* name = (__bridge_transfer NSString*)ABRecordCopyValue(person,
kABPersonFirstNameProperty);
self.firstName = name;
NSString* last = (__bridge_transfer NSString*)ABRecordCopyValue(person,
kABPersonLastNameProperty);
self.lastName = last;
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
NSString *emailId = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emails, 0);//0 for "Home Email" and 1 for "Work Email".
self.email = emailId;
if (!(contacts))
{
contacts = [[NSMutableArray alloc]init];
}
[contacts insertObject:firstName atIndex:0];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.myTableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
@end
回答by Walt Sellers
UITableView must be kept in sync with the data source at all times. Special care must be taken if the data source can change in a background thread.
UITableView 必须始终与数据源保持同步。如果数据源可以在后台线程中更改,则必须特别小心。
When something is added to the data source, call beginUpdate/insert/endUpdate as soon as possible. You don't have to worry about caching these, the UITableView will cache changes to be executed when it determines there is enough cpu time and resources.
当有东西添加到数据源时,尽快调用 beginUpdate/insert/endUpdate。你不必担心缓存这些,当 UITableView 确定有足够的 cpu 时间和资源时,它会缓存要执行的更改。
The moment endUpdates is called, the UITable will ask the dataSource for the number of sections and rows again. If your number of sections and row feeds directly from the dataSource, then number sections and rows, plus insertions, minus deletions must equal the numbers returned by the end calls for numberOfSections and numberOfRowsInSection.
调用 endUpdates 的那一刻,UITable 将再次向 dataSource 询问节数和行数。如果您的节数和行数直接来自数据源,则节数和行数,加上插入,减去删除必须等于 numberOfSections 和 numberOfRowsInSection 的结束调用返回的数字。
One last tip: avoid mixing calls to 'reloadData' and beginUpdate/endUpdate pairs. Use one or the other, not both.
最后一个提示:避免混合调用 'reloadData' 和 beginUpdate/endUpdate 对。使用其中之一,而不是两者。
回答by caribbean
I have encountered same problem as this. All you have to do is change
我遇到了与此相同的问题。你所要做的就是改变
[self.myTableView insertRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];`
to
到
[self.myTableView beginUpdates];
[self.myTableView insertRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
[self.myTableView endUpdates];
From UITableView
Documentation
从UITableView
文档
beginUpdates
beginUpdates
Begin a series of method calls that insert, delete, or select rows and sections of the receiver.
Begin a series of method calls that insert, delete, or select rows and sections of the receiver.
when you use beginUpdates
, you must call endUpdates
and not reloadData
.
当你使用时beginUpdates
,你必须调用endUpdates
而不是reloadData
。
You can check https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.htmlfor more UITableView information.
您可以查看https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html以获取更多 UITableView 信息。
Hope this helps!
希望这可以帮助!
回答by Patrick
The comments above about implementing -tableView:numberOfRowsInSection:
are correct. The assertion is checking the returned value expecting it will increase.
以上关于实施的意见-tableView:numberOfRowsInSection:
是正确的。断言正在检查返回值,期望它会增加。
However since you didn't set your dataSource
on the UITableView
its calling (or not calling) a method that doesn't exist and getting 0
.
但是,由于您没有dataSource
在UITableView
其调用(或不调用)上设置一个不存在的方法并获取0
.
You need to set the myTableView.dataSource
and (since you also implement the delegate protocol) myTableView.delegate
to self
.
您需要将myTableView.dataSource
and(因为您还实现了委托协议)设置myTableView.delegate
为self
。
You're also likely to need something like
你也可能需要类似的东西
- (void)viewDidLoad
{
[super viewDidLoad];
[self.myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
...
}
Unless you're registering that somewhere else or your storyboard has a "Prototype Cell" with the identifier "Cell"
which your code asks for.
除非你在其他地方注册,或者你的故事板有一个带有"Cell"
你的代码要求的标识符的“原型单元” 。
回答by App Dev Guy
I find this problem commonly occurs when I am placing a table view inside of a View Controller. If you're using a UITableViewController jump to 3.
我发现当我在视图控制器中放置一个表视图时,这个问题通常会发生。如果你使用 UITableViewController 跳转到 3。
These steps may help:
这些步骤可能会有所帮助:
1: In your View Controller .h file make sure you add the following:
1:在您的视图控制器 .h 文件中,确保添加以下内容:
@interface YourViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
2: Next create an IBOutlet for your table view by ctrl + drag to your .h class. It should look like:
2:接下来通过 ctrl + 拖动到您的 .h 类为您的表格视图创建一个 IBOutlet。它应该看起来像:
@property (weak, nonatomic) IBOutlet UITableView *tableView;
3: Next step is to ctrl + drag to your View Controllers icon (see image)
3:下一步是按住 ctrl + 拖动到您的 View Controllers 图标(见图)
You need to do this twice selecting:
你需要这样做两次选择:
- delegate
- datasource
Finally, in your .m file, you should have the following method:
最后,在您的 .m 文件中,您应该具有以下方法:
- (void) viewWillAppear:(BOOL)animated{
//[self.tableView beginUpdates];
//[self.tableView endUpdates];
[self.tableView reloadData];
}
You can use either beginUpDates/endUpdates or reloadData, however Apple docs recommend reloadData.
您可以使用 beginUpDates/endUpdates 或 reloadData,但 Apple 文档建议使用 reloadData。
Once done your table should work fine.
完成后,您的桌子应该可以正常工作。
回答by bhavya kothari
You need to maintain count for contacts arrayand increment accordingly.
and while creating indexPath you need to set appropriate indexPathForRow: and section count(if required).
您需要维护联系人数组的计数并相应地增加。
在创建 indexPath 时,您需要设置适当的 indexPathForRow: 和节数(如果需要)。
- (void)displayPerson:(ABRecordRef)person
{
..........
[contacts insertObject:firstName atIndex:0];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; // you cant do this increment appropriately
.........
}
回答by Narasimha Nallamsetty
Please check your tableview datasource and delegate methods. You may be passing empty array to datasource methods. And don't forget to reload tableview after getting data.
请检查您的 tableview 数据源和委托方法。您可能将空数组传递给数据源方法。并且不要忘记在获取数据后重新加载 tableview。
回答by coyer
I know it's stupid - I got the same error because I forgot to set the delegate and dataSource.
我知道这很愚蠢 - 我遇到了同样的错误,因为我忘记设置委托和数据源。
So after inserting rows and doing tableView.endUpdates()
the tableView thought it must have some rows - but due to the unlinked dataSource
, it has not.
所以在插入行并执行tableView.endUpdates()
tableView 后认为它必须有一些行 - 但由于未链接dataSource
,它没有。