表格单元格显示在表视图中的错误部分

时间:2013-01-13 23:08:58

标签: iphone objective-c xcode core-data

DataModel.h代码文件

#import "DataModel.h"
#import <CoreData/CoreData.h>
#import "SettingsEntity.h"
#import "Constants.h"

@implementation DataModel

NSManagedObjectContext *managedObjectContextEntity;
NSManagedObjectContext *managedObjectContextMessage;
NSManagedObjectModel *managedObjectModel;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
NSEntityDescription *theSettingsEntity;
NSEntityDescription *theMessagesEntity;


-(id) init
{

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"SOW" withExtension:@"momd"];
    managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    NSError *error = nil;

    NSURL *storeURL = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:[Constants SQLLiteDB]];

    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];

    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    if (persistentStoreCoordinator != nil) {
        managedObjectContextEntity = [[NSManagedObjectContext alloc] init];
        [managedObjectContextEntity setPersistentStoreCoordinator:persistentStoreCoordinator];

        managedObjectContextMessage = [[NSManagedObjectContext alloc] init];
        [managedObjectContextMessage setPersistentStoreCoordinator:persistentStoreCoordinator];
    }

    theSettingsEntity = [NSEntityDescription entityForName:@"SettingsEntity" inManagedObjectContext:managedObjectContextEntity];
    theMessagesEntity = [NSEntityDescription entityForName:@"MessageEntity" inManagedObjectContext:managedObjectContextMessage];

    return self;
}



-(void) SaveSetting: (SettingsEntity *)setting
{
    NSError *error = nil;

    if (managedObjectContextEntity != nil) {
        if ([managedObjectContextEntity hasChanges] && ![managedObjectContextEntity save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
        else {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Confirmation" message:@"Settings were saved successfully." delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
            [alert show];
        }

    }
}

-(void) SaveMessage: (MessageEntity *)message
{
    NSError *error = nil;

    if (managedObjectContextMessage != nil) {
        if ([managedObjectContextMessage hasChanges] && ![managedObjectContextMessage save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        } 
    }

}

-(NSArray *) GetSettingsResult
{

    NSManagedObjectContext *context = managedObjectContextEntity;
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    [request setEntity:theSettingsEntity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"enteredDateTime" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [request setSortDescriptors:sortDescriptors];


    NSArray *results = [context executeFetchRequest:request error:nil];

    return results;
}

-(SettingsEntity *) GetSettingsEntity
{
    SettingsEntity *settingsEntity = [NSEntityDescription 
                                      insertNewObjectForEntityForName:[theSettingsEntity name] 
                                      inManagedObjectContext:managedObjectContextEntity];
    return settingsEntity;
}

-(NSArray *) GetMessageResult
{
    NSFetchRequest *request = [self GetMessageFetchRequest];
    NSArray *results = [managedObjectContextMessage executeFetchRequest:request error:nil];

    return results;
}

-(NSFetchRequest *) GetMessageFetchRequest
{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];

    [request setEntity:theMessagesEntity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"sentDateTime" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [request setSortDescriptors:sortDescriptors];

    return request;
}

-(NSFetchedResultsController *)  GetMessageFetchResultsController
{
    NSFetchRequest *fetchRequest = [self GetMessageFetchRequest];
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContextMessage sectionNameKeyPath:@"typeMessage" cacheName:nil];
    return aFetchedResultsController;
}

-(MessageEntity *) GetMessageEntity
{
    MessageEntity *mEntity = [NSEntityDescription 
                                      insertNewObjectForEntityForName:[theMessagesEntity name] 
                                      inManagedObjectContext:managedObjectContextMessage];
    return mEntity;
}



@end

HistoryTableView代码文件如下:

#import "HistoryTableViewController.h"
#import "MessageEntity.h"
#import "DataModel.h"
#import "HistoryDetailViewController.h"
#import "Constants.h"

@interface HistoryTableViewController ()
 - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
@end


@implementation HistoryTableViewController

//todo: zulfiqar review this line of code.
@synthesize fetchedResultsController = __fetchedResultsController;


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

- (void)awakeFromNib
{
    [super awakeFromNib];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationItem.rightBarButtonItem = self.editButtonItem;

    //todo: get fetched controller here.. and reuse it every where in rest of this class.

}

/* faisal code starts here */
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{

    NSFetchedResultsController *c = [self fetchedResultsController];
    NSArray *titles = [c sectionIndexTitles];
    NSString *title = titles[section];

    if ([title isEqualToString:@"E"])
    {
        return [Constants Email];
    }
    else if([title isEqualToString:@"T"])
    {
        return [Constants Text];
    }
    else
    {
        return [Constants Call];
    }
}

- (NSArray *)sectionIndexTitlesForTableView: (UITableView *)aTableView
{
    NSFetchedResultsController *c = [self fetchedResultsController];
    return [c sectionIndexTitles];
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSFetchedResultsController *c = [self fetchedResultsController];
    id<NSFetchedResultsSectionInfo> sectionInfo = c.sections[section];
    return sectionInfo.numberOfObjects;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    NSFetchedResultsController *c = [self fetchedResultsController];
    return c.sections.count;
}

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

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{

    NSIndexPath *path = self.tableView.indexPathForSelectedRow;
    HistoryDetailViewController *hdvc = segue.destinationViewController;
    NSFetchedResultsController *c = [self fetchedResultsController];
    MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:path];
    hdvc.currentMessageEntity = message;

}

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

#pragma mark - Table view data source
/*
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSFetchedResultsController *c = [self fetchedResultsController];
    id <NSFetchedResultsSectionInfo> sectionInfo = c.sections[section];

    return sectionInfo.numberOfObjects;
}
*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSFetchedResultsController *c = [self fetchedResultsController];

    NSString *CellIdentifier = [NSString stringWithFormat:@"Cell"];// %d_%d",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier  forIndexPath:indexPath];
    MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:indexPath];
    cell.textLabel.text = message.typeMessage;

    return cell;
    /*

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"EEE. MMM. dd, yyyy HH:mm"];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    NSFetchedResultsController *c = [self fetchedResultsController];
    MessageEntity *message = (MessageEntity *)[c objectAtIndexPath:indexPath];
    NSString *sentDateTime = [dateFormat stringFromDate:message.sentDateTime];

    NSString *contactAdd;

    NSLog(message.typeMessage);
    if ([message.typeMessage isEqualToString:[Constants Email]])
    {
        contactAdd = message.toEmailAddress;
    }
    else
    {
        NSString *unformatted = message.toPhoneNumber;
        NSArray *stringComponents = [NSArray arrayWithObjects:[unformatted substringWithRange:NSMakeRange(0, 3)],
                                     [unformatted substringWithRange:NSMakeRange(3, 3)],
                                     [unformatted substringWithRange:NSMakeRange(6, [unformatted length]-6)], nil];

        contactAdd = [NSString stringWithFormat:@"(%@) %@-%@", [stringComponents objectAtIndex:0], [stringComponents objectAtIndex:1], [stringComponents objectAtIndex:2]];
    }


    NSString *header = [[NSString alloc] initWithFormat:@"%@",contactAdd];
    NSString *detail = [[NSString alloc] initWithFormat:@"%@ on %@", message.sentName, sentDateTime];

    cell.detailTextLabel.text = detail;
    cell.textLabel.text = header;

    return cell;
     */
}


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


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSFetchedResultsController *c = [self fetchedResultsController];
        NSManagedObject *object = [c objectAtIndexPath:indexPath];
        NSManagedObjectContext *context = self.fetchedResultsController.managedObjectContext;
        [context deleteObject:object];
        NSError *error = nil;
        if (![context save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }

    }   
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // The table view should not be re-orderable.
    return NO;
}

- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath {

    [tableView reloadData];

}

- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil) {
        return __fetchedResultsController;
    }    
    DataModel *data = [[DataModel alloc]init];
    NSFetchedResultsController *aFetchedResultsController = [data GetMessageFetchResultsController];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __fetchedResultsController;
}  

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch(type) {
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch(type) {
        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}


#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

我的历史记录表视图如下所示:

enter image description here

**Q. Why Email and Call are getting into wrong section?** 

1 个答案:

答案 0 :(得分:1)

如果为获取的结果控制器设置sectionNameKeyPath,则还必须将第一个排序描述符添加到使用相同键的提取请求(或生成相同相对排序的键)。

因此,对于sectionNameKeyPath:@"typeMessage",您应该为键“typeMessage”添加一个排序描述符:

NSSortDescriptor *sort1 = [[NSSortDescriptor alloc] initWithKey:@"typeMessage" ascending:YES];
NSSortDescriptor *sort2 = [[NSSortDescriptor alloc] initWithKey:@"sentDateTime" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sort1, sort2, nil];
[request setSortDescriptors:sortDescriptors];