简体   繁体   English

从表视图中删除行中获取SIGABRT

[英]Getting a SIGABRT From Deleting a Row in a Table View

I am trying to have a table view list a number of objects that are stored in an array and it's working fine other than when I try to delete a row, it throws a SIGABRT. 我试图让一个表视图列出存储在数组中的许多对象,并且除了我尝试删除一行时,它会抛出SIGABRT,它的工作正常。 I checked at it is correctly updating the array. 我检查它是否正确更新了阵列。 It seems that the SIGABRT has something to do with the number of sections in the table. 似乎SIGABRT与表中的节数有关。 Here is the code for the table view controller: 这是表视图控制器的代码:

CalendarViewController.h CalendarViewController.h

#import <UIKit/UIKit.h>
#import "Job.h"
#import "Shift.h"
#import "AppDelegate.h"

@interface CalendarViewController : UITableViewController

@property (nonatomic, strong) NSMutableArray *currentShiftsList;
@property (nonatomic, strong) AppDelegate *dataCenter;

@end

CalendarViewController.m CalendarViewController.m

#import "CalendarViewController.h"

@interface CalendarViewController ()

@property (nonatomic, strong) NSMutableDictionary *sections;
@property (nonatomic, strong) NSArray *sortedShifts;
@property (strong, nonatomic) NSDateFormatter *sectionDateFormatter;
@property (strong, nonatomic) NSDateFormatter *cellDateFormatter;

@end

@implementation CalendarViewController

@synthesize sections, sortedShifts, currentShiftsList, dataCenter, sectionDateFormatter, cellDateFormatter;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (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;
}

- (NSDate *)dateByAddingYears:(NSInteger)numberOfYears toDate:(NSDate *)inputDate
{
    // Use the user's current calendar
    NSCalendar *calendar = [NSCalendar currentCalendar];

    NSDateComponents *dateComps = [[NSDateComponents alloc] init];
    [dateComps setYear:numberOfYears];

    NSDate *newDate = [calendar dateByAddingComponents:dateComps toDate:inputDate options:0];
    return newDate;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    dataCenter = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    currentShiftsList = [[NSMutableArray alloc] initWithArray:dataCenter.shiftsList];

    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];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    self.navigationItem.rightBarButtonItem = self.editButtonItem;

    self.sections = [NSMutableDictionary dictionary];
    for (Shift *shift in dataCenter.shiftsList) {

        // Reduce event start date to date components (year, month, day)
        NSDate *dateRepresentingThisDay = [self dateAtBeginningOfDayForDate:shift.startDate];

        // If we don't yet have an array to hold the events for this day, create one
        NSMutableArray *shiftsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
        if (shiftsOnThisDay == nil) {
            shiftsOnThisDay = [NSMutableArray array];

            // Use the reduced date as dictionary key to later retrieve the event list this day
            [self.sections setObject:shiftsOnThisDay forKey:dateRepresentingThisDay];
        }

        // Add the event to the list for this day
        [shiftsOnThisDay addObject:shift];
    }

    // Create a sorted list of days
    NSArray *unsortedShifts = [self.sections allKeys];
    self.sortedShifts = [unsortedShifts sortedArrayUsingSelector:@selector(compare:)];
}



- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return [self.sections count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    NSDate *dateRepresentingThisDay = [self.sortedShifts objectAtIndex:section];
    NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
    return [eventsOnThisDay count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *reuseIdentifier = @"shifts";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

    NSDate *dateRepresentingThisDay = [self.sortedShifts objectAtIndex:indexPath.section];
    NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
    Shift *shift = [eventsOnThisDay objectAtIndex:indexPath.row];

    cell.textLabel.text = shift.jobtitle;

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"h:mm a"];

    NSString *start = [formatter stringFromDate:shift.startDate];
    NSString *end = [formatter stringFromDate:shift.endDate];

    NSString *detail = [[NSString alloc] initWithFormat:@"%@ to %@", start, end];
    cell.detailTextLabel.text = detail;
    return cell;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    NSDate *dateRepresentingThisDay = [self.sortedShifts objectAtIndex:section];
    return [self.sectionDateFormatter stringFromDate:dateRepresentingThisDay];
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/


// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source

        [currentShiftsList removeObjectAtIndex:indexPath.row];
        dataCenter.shiftsList = currentShiftsList;

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     */
}

@end

This doesn't make sense to me. 这对我来说没有意义。

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];

Why isn't it just: 为什么不只是:

[tableView deleteRowsAtIndexPaths:indexPath.row withRowAnimation:UITableViewRowAnimationFade];

Also remember a reload TableView after delete (if you want it). 还记得删除后重新加载TableView(如果需要)。

When you delete a row, you are removing an item from the currentShiftsList array. 删除行时,就是从currentShiftsList数组中删除一项。 However, you are not using that array in your UITableViewDataSource related methods. 但是,您没有在与UITableViewDataSource相关的方法中使用该数组。 The TableView is expecting there to be 1 less item from its DataSource, but you will be returning the original number of items instead. TableView期望其DataSource中的项目减少1个,但您将返回原来的项目数。

Overall, things are very confusing because you have several collections that are trying to manage the same set of data (or copies of that data). 总体而言,事情非常混乱,因为您有多个试图管理同一组数据(或该数据的副本)的集合。 Try looking into CoreData and the NSFetchedResultsController which is specifically made to managed a set of data and propagate any changes to a UITableView. 尝试研究CoreData和NSFetchedResultsController,它们专门用于管理一组数据,并将所有更改传播到UITableView。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM