Obj-C语言 应用程序崩溃,如果tableview部分是空的?



我使用下面的代码按字母顺序组织我的tableView。过滤器工作正确,但如果其中一个部分不包含结果(即。字母" a "没有返回,这会导致我的应用崩溃,因为tableView试图用不存在的数据填充一个单元格。知道我该怎么预防吗?

ViewController.m

- (void)viewDidLoad {
[super viewDidLoad];

self.clientSections = [NSArray arrayWithObjects:@"#", @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n", @"o", @"p", @"q", @"r", @"s", @"t", @"u", @"v", @"w", @"x", @"y", @"z", nil];


NSMutableDictionary *viewParams1 = [NSMutableDictionary new];
[viewParams1 setValue:@"cdata" forKey:@"view_name"];
[DIOSView viewGet:viewParams1 success:^(AFHTTPRequestOperation *operation, id responseObject) {

self.clients = [responseObject mutableCopy];


NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"last name" ascending:YES];

self.clientsAZ = [self.clients sortedArrayUsingDescriptors:@[sort]];


} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failure: %@", [error localizedDescription]);
}];


-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {


return [self.clientSections count];

}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.clientSections;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

return [self.clientSections objectAtIndex:section];


}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {


self.finalfiltered = [self.clientsAZ  filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(%K beginswith[cd] %@)", @"last name", [self.clientSections objectAtIndex:section]]];


return [self.finalfiltered count];

}


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


static NSString *ClientTableIdentifier = @"ClientTableViewCell";

ClientTableViewCell *cell = (ClientTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:ClientTableIdentifier];

if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ClientTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];

}


NSString *photo = [self.finalfiltered valueForKey:@"client photo"][indexPath.row];

NSString *first = [self.finalfiltered valueForKey:@"first name"][indexPath.row];

NSString *last = [self.finalfiltered valueForKey:@"last name"][indexPath.row];

NSString *telephone = [self.finalfiltered valueForKey:@"phone"][indexPath.row];

NSString *fullName = [NSString stringWithFormat:@"%@ %@", first, last];

cell.clientName.text = fullName;
cell.subtext.text = telephone;

NSURL *imageUrl = [NSURL URLWithString:photo];
NSLog(@"The photo url is %@", photo);
[cell.clientPhoto setImageWithURL:imageUrl];

return cell;


}


}

编辑:这是我记录self.finalfiltered时返回的内容。注意,我是按姓氏排序的。顺序似乎是正确的。

2021-02-10 16:53:34.905601-0800 [1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.905846-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.906076-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.906335-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.906566-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.906772-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.907025-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.907558-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.907772-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.908296-0800 -[1784:532468] THE FINAL FILTER (
{
body = none;
city = Victoria;
"client photo" = "/stockphotos/person5.png";
country = Canada;
email = "thomas.ingram@outlook.com";
"first name" = Thomas;
"last name" = Ingram;
"mailing address" = "502 Catherine Street";
"mailing address 2" = "Apt 403";
nid = 127;
"node_title" = "Thomas Ingram";
notes = "test notes";
phone = "250-998-0389";
scheduleddate = "Feb 8 2021 1:00 PM";
scheduledtime = none;
"state or province" = BC;
"zip code" = "V9A 3T3";
}
)
2021-02-10 16:53:34.908833-0800 -[1784:532468] THE FINAL FILTER (
{
body = none;
city = Toronto;
"client photo" = "/stockphotos/person2.png";
country = Canada;
email = "andrea@gmail.com";
"first name" = Andrea;
"last name" = Johnson;
"mailing address" = "227 Willow Avenue";
"mailing address 2" = "Unit 2034";
nid = 124;
"node_title" = "Andrea Johnson";
notes = "test notes";
phone = "416-223-2397";
scheduleddate = "Feb 8 2021 07:00 PM";
scheduledtime = "5:45 PM";
"state or province" = ON;
"zip code" = "M5M 1W4";
}
)
2021-02-10 16:53:34.909541-0800 -[1784:532468] THE FINAL FILTER (
{
body = none;
city = Burnaby;
"client photo" = "/sites/default/files/stored/1612926759.jpg";
country = Canada;
email = email@email.com;
"first name" = Cody;
"last name" = Lin;
"mailing address" = "4036 Pandora Street";
"mailing address 2" = "-";
nid = 171;
"node_title" = "Cody Lin”;
notes = "test notes”;
phone = "604-250-7422";
scheduleddate = none;
scheduledtime = none;
"state or province" = BC;
"zip code" = V5C2A9;
}
)
2021-02-10 16:53:34.910439-0800 -[1784:532468] THE FINAL FILTER (
{
body = none;
city = "New York City";
"client photo" = "/stockphotos/person4.png";
country = US;
email = "mlevy39@gmail.com";
"first name" = Michael;
"last name" = Levy;
"mailing address" = "22 Lexington Avenue";
"mailing address 2" = "Apt 102";
nid = 126;
"node_title" = "Michael Levy";
notes = "test notes";
phone = "212-983-0029";
scheduleddate = "Feb 10 2021 1:00 PM";
scheduledtime = none;
"state or province" = NY;
"zip code" = 90020;
},
{
body = none;
city = London;
"client photo" = "/stockphotos/person1.png";
country = Canada;
email = "janinejlohr@gmail.com";
"first name" = Janine;
"last name" = Monroe;
"mailing address" = "909 Fake Street";
"mailing address 2" = "Unit 4103";
nid = 123;
"node_title" = "Janine Monroe";
notes = "test notes";
phone = "778-028-2938";
scheduleddate = "Feb 14 2021 7:37 PM, Feb 17 2021 9:00 AM";
scheduledtime = none;
"state or province" = BC;
"zip code" = "V6E 4V2";
}
)
2021-02-10 16:53:34.911207-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.911423-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.911630-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.911834-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.912033-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.912233-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.912431-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.913457-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.913671-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.913931-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.914378-0800 -[1784:532468] THE FINAL FILTER (
{
body = none;
city = Vancouver;
"client photo" = "/stockphotos/person3.png";
country = Canada;
email = "cali.wright@gmail.com";
"first name" = Cali;
"last name" = Wright;
"mailing address" = "667 Fake Street";
"mailing address 2" = "Apt 4102";
nid = 125;
"node_title" = "Cali Wright";
notes = "test notes”;
phone = "778-867-7184";
scheduleddate = none;
scheduledtime = none;
"state or province" = BC;
"zip code" = none;
}
)
2021-02-10 16:53:34.914652-0800 -[1784:532468] THE FINAL FILTER (
)
2021-02-10 16:53:34.914868-0800 -[1784:532468] THE FINAL FILTER (
)

发生的崩溃是:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'

最后,在代码中,它似乎在这行之前崩溃了:

NSString *photo = [self.finalfiltered valueForKey:@"client photo"][indexPath.row];

你的方法是始终返回27在你的表视图部分的数量,对应于数字和字母A-Z。但是,UITableView不能有0行的section。这意味着当您的数据不包含以" & "开头的姓氏时,您会遇到问题,例如;第1节返回0,但这是不允许的。tableview仍然会请求空section的第0行你会得到一个数组边界异常

为了得到答案,我简化了单元格显示代码,因为我不想完全填充所有数据字段并设置自定义单元格(您应该使用对象来封装数据模型,而不是字典)。

大部分工作是在splitClients方法中完成的-这为每个节和节标题创建适当的数组。在这段代码中,我确保数据是按排序顺序创建的,但是您可以像在代码中那样对数据进行排序。

通过创建正确的数组,您可以看到numberOfSectionsnumberOfRowsInSection是多么简单-您希望这些函数以及cellForRowAt是有效的,因为它们将在表视图滚动时被多次调用。

另一个值得注意的方法是sectionForSectionIndexTitle——因为不是所有的索引部分都可以被填充,这个函数用于返回最接近填充的部分,所以如果您选择"b"而且没有"& & "s",它会滚动到"& "

@interface ViewController ()
@property NSArray<NSDictionary *> *clients;
@property NSArray<NSArray *> *sectionClients;
@property NSArray<NSString *> *sectionLetters;
@property NSArray<NSString *> *sectionHeaders;
@property IBOutlet UITableView *tableView;
@end
@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
self.sectionLetters = [NSArray arrayWithObjects:@"#", @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n", @"o", @"p", @"q", @"r", @"s", @"t", @"u", @"v", @"w", @"x", @"y", @"z", nil];
// Do any additional setup after loading the view.

NSMutableArray *clients = [NSMutableArray new];
[clients addObject:[self clientWithFirstname:@"Andrew" lastName:@"67Anderson"]];
[clients addObject:[self clientWithFirstname:@"Andrew" lastName:@"Anderson"]];
[clients addObject:[self clientWithFirstname:@"Zaphod" lastName:@"Beeblebrox"]];
[clients addObject:[self clientWithFirstname:@"Bob" lastName:@"Carlson"]];
[clients addObject:[self clientWithFirstname:@"David" lastName:@"Carlson"]];
[clients addObject:[self clientWithFirstname:@"Anthony" lastName:@"Edwards"]];
[clients addObject:[self clientWithFirstname:@"Griff" lastName:@"Jones"]];
[clients addObject:[self clientWithFirstname:@"Sara" lastName:@"Kelly"]];
[clients addObject:[self clientWithFirstname:@"Mabel" lastName:@"Maloney"]];
[clients addObject:[self clientWithFirstname:@"Horatio" lastName:@"Newton"]];
[clients addObject:[self clientWithFirstname:@"Josie" lastName:@"Peters"]];
[clients addObject:[self clientWithFirstname:@"Mel" lastName:@"Smith"]];
[clients addObject:[self clientWithFirstname:@"Michael" lastName:@"Taylor"]];
[clients addObject:[self clientWithFirstname:@"Mary" lastName:@"Zax"]];

self.clients = [clients copy];

[self splitClients];
NSLog(@"Done splitting");
}
-(NSDictionary *)clientWithFirstname:(NSString *)firstName lastName:(NSString *)lastName {
NSMutableDictionary *dict = [NSMutableDictionary new];
dict[@"first name"] = firstName;
dict[@"last name"] = lastName;
return dict;
}
-(void)splitClients {

NSMutableArray *sectionClients = [NSMutableArray new];
NSMutableArray *sectionHeaders = [NSMutableArray new];

// Look for last names that start with a digit using a regex
NSArray *digitClients = [self.clients filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(%K MATCHES %@)",@"last name",@"[0-9].*" ]];

// Add a section for digit names if any were found
if ([digitClients count] > 0) {
[sectionClients addObject:digitClients];
[sectionHeaders addObject:@"#"];
}

// Now check for names starting with each letter of the alphabet
for (NSString *letter in self.sectionLetters) {

NSArray *letterArray = [self.clients filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(%K beginswith[cd] %@)", @"last name",letter]];
// If any matching names were found, add them as a new section
if ([letterArray count] >0) {
[sectionClients addObject:letterArray];
[sectionHeaders addObject:letter];
}
}

self.sectionClients = [sectionClients copy];
self.sectionHeaders = [sectionHeaders copy];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sectionClients count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.sectionLetters;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

return self.sectionHeaders[section];

}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.sectionClients[section] count];
}
- (NSInteger)tableView:(UITableView *)tableView
sectionForSectionIndexTitle:(NSString *)title
atIndex:(NSInteger)index {

NSInteger targetSection = 0;

for (NSString *letter in self.sectionHeaders) {
NSComparisonResult result = [title compare:letter];
// If the section index is >= the target index, break and exit
if (result == NSOrderedAscending || result == NSOrderedSame) {
break;
}
// Otherwise increment the section number
targetSection++;
}

return targetSection;
}

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

NSDictionary *client = self.sectionClients[indexPath.section][indexPath.row];

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", client[@"first name"], client[@"last name"]];

return cell;

}
@end

相关内容

  • 没有找到相关文章

最新更新