我有一个按部分分组的tableview,按日期排序,每个部分基本上是一天,每一行都是当天的约会/事件。我从一个nsmutablearray获取我的事件,并且它们有一个“startDate”属性,我通过该属性对表进行排序。我在尝试从部分删除行时遇到了麻烦。
- 如果我有1行5行,那么我可以单独删除它们,最后一行也会删除该部分。
- 如果我有超过1个部分,当我尝试删除部分中的最后一行时,它会崩溃。
这是我的代码:
@interface AgendaViewController ()
@property (nonatomic,strong) NSString *path;
@property (strong, nonatomic) NSMutableDictionary *sections;
@property (strong, nonatomic) NSMutableArray *sortedDays;
@property (strong, nonatomic) NSDateFormatter *sectionDateFormatter;
@property (strong, nonatomic) NSDateFormatter *cellDateFormatter;
@end
@implementation AgendaViewController
@synthesize events = _events;
-(IBAction)menuButtonTapped:(id)sender{
[self.slidingViewController anchorTopViewToRightAnimated:YES];
}
-(IBAction)unwindToAgenda:(UIStoryboardSegue *)segue{
AddAgendaEntryViewController *source = [segue sourceViewController];
AgendaEntry *event = source.agendaEntry;
if (event){
[self.events addObject:event];
[self saveList];
[self createSections];
[self.tableView reloadData];
}
}
- (void)saveList
{
[NSKeyedArchiver archiveRootObject:self.events toFile:self.path];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
self.path = [self.path stringByAppendingPathComponent:@"TodoList.txt"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:self.path]) {
self.events = [[NSMutableArray alloc] init];
} else {
self.events = [[NSKeyedUnarchiver unarchiveObjectWithFile:self.path] mutableCopy];
}
[self setMenuGesture];
[self fetchEvents];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
self.tableView.separatorColor = [UIColor colorWithRed:224.0/255.0 green:224.0/255.0 blue:224.0/255.0 alpha:1.0f];
[self createSections];
//date formatteri
self.sectionDateFormatter = [[NSDateFormatter alloc] init];
[self.sectionDateFormatter setDateStyle:NSDateFormatterLongStyle];
[self.sectionDateFormatter setTimeStyle:NSDateFormatterNoStyle];
self.cellDateFormatter = [[NSDateFormatter alloc] init];
[self.cellDateFormatter setDateStyle:NSDateFormatterNoStyle];
[self.cellDateFormatter setTimeStyle:NSDateFormatterShortStyle];
}
-(void)createSections{
self.sections = nil;
self.sections = [[NSMutableDictionary alloc]init];
for (AgendaEntry *entry in self.events){
NSDate *dateRepresentingThisDay = [self dateAtBeginningOfDayForDate:entry.startDate];
NSMutableArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
if(eventsOnThisDay == nil){
eventsOnThisDay = [NSMutableArray array];
[self.sections setObject:eventsOnThisDay forKey:dateRepresentingThisDay];
}
[eventsOnThisDay addObject:entry ];
NSArray *unsortedDays = [self.sections allKeys];
self.sortedDays = [[unsortedDays sortedArrayUsingSelector:@selector(compare:)] mutableCopy];}
NSLog(@"NUMBER OF SECTIONS IN TABLEVIEW: %lu",(unsigned long)[self.sections count]);
// [self.tableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.sections count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(void)fetchEvents{
//Apel catre webserver pentru eventuri.
}
-(void)setEvents:(NSMutableArray *)events{
_events = events;
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:section];
NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
return [eventsOnThisDay count];
}
/*- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:section];
NSString *title = [self.sectionDateFormatter stringFromDate:dateRepresentingThisDay];
return title;
}*/
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger) section{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 15)];
UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, self.view.frame.size.width, 15)];
lbl.backgroundColor = [UIColor clearColor];
lbl.textAlignment = NSTextAlignmentCenter;
lbl.font = [UIFont systemFontOfSize:12];
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:section];
NSString *title = [self.sectionDateFormatter stringFromDate:dateRepresentingThisDay];
lbl.text = title;
[view addSubview:lbl];
[view setBackgroundColor:[UIColor colorWithRed:166/255.0 green:177/255.0 blue:186/255.0 alpha:0.3]]; //your background color...
return view;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Event Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell..
//AgendaEntry *event = [self.events objectAtIndex:indexPath.row];
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:indexPath.section];
NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
AgendaEntry *event = [eventsOnThisDay objectAtIndex:indexPath.row];
UIImageView *mappin = (UIImageView *)[cell viewWithTag:4] ;
mappin.image = [UIImage imageNamed:@"map_pin"];
UILabel *companyName = (UILabel *)[cell viewWithTag:1];
companyName.text = event.companyName;
UILabel *eventType = (UILabel *) [cell viewWithTag:3];
eventType.text = event.eventType;
UILabel *dateOfEvent = (UILabel *) [cell viewWithTag:2];
dateOfEvent.text = [self.cellDateFormatter stringFromDate:event.startDate];
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.events removeObjectAtIndex:indexPath.row];
[self createSections];
[self saveList];
[tableView beginUpdates];
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:indexPath.section];
NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
if ([eventsOnThisDay count] > 0){
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}else{
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]
withRowAnimation:UITableViewRowAnimationFade];
}
[tableView endUpdates];
}
[self.tableView reloadData];
}
-(NSMutableArray *)sortedDays{
if (!_sortedDays) _sortedDays = [[NSMutableArray alloc]init];
return _sortedDays;
}
-(void)setMenuGesture{
id<ECSlidingViewControllerDelegate> transition = self.zoomAnimationController ;
self.slidingViewController.delegate = transition;
self.slidingViewController.topViewAnchoredGesture = ECSlidingViewControllerAnchoredGestureTapping | ECSlidingViewControllerAnchoredGesturePanning;
self.slidingViewController.customAnchoredGestures = @[];
// [self.navigationController.view addGestureRecognizer:self.slidingViewController.panGesture];
}
- (ZoomAnimationController *)zoomAnimationController {
if (_zoomAnimationController) return _zoomAnimationController;
_zoomAnimationController = [[ZoomAnimationController alloc] init];
return _zoomAnimationController;
}
-(NSMutableArray *)events{
[self sortEvents];
return _events;
}
/*- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 30;
}*/
- (NSDate *)dateAtBeginningOfDayForDate:(NSDate *)inputDate
{
// Use the user's current calendar and time zone
NSCalendar *calendar = [NSCalendar currentCalendar];
NSTimeZone *timeZone = [NSTimeZone systemTimeZone];
[calendar setTimeZone:timeZone];
// Selectively convert the date components (year, month, day) of the input date
NSDateComponents *dateComps = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit fromDate:inputDate];
// Set the time components manually
[dateComps setHour:0];
[dateComps setMinute:0];
[dateComps setSecond:0];
// Convert back
NSDate *beginningOfDay = [calendar dateFromComponents:dateComps];
return beginningOfDay;
}
-(void)sortEvents{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"startDate" ascending:TRUE];
[_events sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
@end
我得到的错误:
由于未捕获的异常'NSRangeException'而终止应用程序,原因:'*** - [__ NSArrayM objectAtIndex:]:索引1超出边界[0 .. 0]'`
答案 0 :(得分:0)
使用yourArray [removeObjectAtIndex:indexpath];它会更新你的数组。
答案 1 :(得分:0)
在commitEditingStyle
功能中,您首先删除该部分(我假设在这种情况下为第1部分......),然后在[tableView beginUpdates];
和[tableView endUpdates];
行之间更新您的表格。您遇到的问题是您使用原始部分索引(1)访问您的sortedDays数组,该索引不再存在 - 您刚删除它; - ):
NSDate * dateRepresentingThisDay = [self.sortedDays objectAtIndex:indexPath.section];
答案 2 :(得分:0)
deleteForRowAtIndexPath
中的逻辑似乎导致了这个问题。
您正在做的只是根据self.events
从indexPath.row
删除。但是当您有超过1个部分时,您的self.events
和eventsOnThisDay
数组可能不会保持相同的索引。
我建议您以与将其加载到tableView相同的方式删除该项目。例如,在deleteRowAtIndexPath
,
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:indexPath.section];
NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
[eventsOnThisDay removeObjectAtIndex:indexPath.row];
//If there are no more events on this day, then just delete the section also.
if([eventsOnThisDay count] == 0){
[self.sections removeObjectForKey:dateRepresentingThisDay];
[self.sortedDays removeObjectAtIndex:indexPath.section];
}
[self.tableView reloadData];
//You should also update your self.events list also accordingly.
希望这有帮助。