简体   繁体   中英

UITableView does not show new entries when data object conforms to NSCoding

When I make an object class conform to NSCoding, the tableView does not show new entries. Suspected it had to do with the object initialization but cannot solve it. Might be very basic but cannot find the error. Here is the code I simplified to post:

Custom Object:

//  DataObject.h
#import <Foundation/Foundation.h>
@interface DataObject : NSObject {
NSString *name;
}
@property (nonatomic, copy) NSString *name;
@end

//  DataObject.m
#import "DataObject.h"
@implementation DataObject  
@synthesize name;

- (void)encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:name forKey:@"name"];
}

- (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
if (!self) return nil;

name = [[decoder decodeObjectForKey:@"name"] retain];
return self;
}

These is the TableView root controller - Have omitted a few methods:

//  RootViewController.h
#import <UIKit/UIKit.h>
@interface RootViewController : UITableViewController {
NSMutableArray *list;
}
@property (nonatomic, retain) NSMutableArray *list;

- (void)add:(id)sender;
- (NSString *)dataFilePath;

@end

//  RootViewController.m
#import "RootViewController.h"
#import "DataObject.h"

@implementation RootViewController
@synthesize list;

- (void)add:(id)sender
{   
DataObject *newEntry = [[DataObject alloc] init];
newEntry.name = @"Willy";
[self.list addObject:newEntry];

[self.tableView reloadData];

// Scroll table view to last row
if ([list count] > 1) {
    NSUInteger index = list.count - 1;
    NSIndexPath *lastRow = [NSIndexPath indexPathForRow:index inSection: 0];
    [self.tableView scrollToRowAtIndexPath: lastRow atScrollPosition:       UITableViewScrollPositionTop animated: YES];
}

[newEntry release];

}

- (NSString *)dataFilePath 
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:@"datafile"];
}

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

self.title = @"Names";
self.list = [[NSMutableArray alloc] init];

NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
self.list = tempArray;

UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(applicationWillResignActive:) 
                                             name:UIApplicationWillResignActiveNotification
                                           object:app];


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

UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
                              initWithTitle:@"Add"
                              style:UIBarButtonItemStylePlain
                              target:self
                              action:@selector(add:)];
self.navigationItem.leftBarButtonItem = addButton;
[addButton release];

[self.tableView reloadData];

}

- (void)applicationWillResignActive:(NSNotification *)notification;
{
[NSKeyedArchiver archiveRootObject:self.list toFile:[self dataFilePath]];
}


- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
[super viewWillAppear:animated];
}

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [list 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] autorelease];
    }

// Configure the cell.
NSUInteger row = [indexPath row];
DataObject *oneName = [self.list objectAtIndex:row];
cell.textLabel.text = oneName.name;

    return cell;
}

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

    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source.
        NSUInteger row = [indexPath row];
        [self.list removeObjectAtIndex:row];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   

}


@end

Oh, man I am so embarrassed...It had nothing to do with NSCoding directly but when I made the data class NSCoding compliant I added in viewDidLoad:

NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
self.list = tempArray;

The first line is fine, but the second assigned a new pointer address to self.list and the tempArray was later autoreleased... As this line was not executed in the "not NSCoding compliant" version it appeared to work then and not when encodeWithCoder and initWithCoder were implemented.

Because of this self.list was nil instead of being initialized and ready when in the add: method I added a new instance. It was created fine, but never added to the array and therefore never showed in the tableView.

This was easily fixed using instead in viewDidLoad:

NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
[self.list addObjectsFromArray:tempArray];

Worst part is that I was pulling my hair because of this and was convinced it was because of NSCoding and the initialization of objects...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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