Search code examples
iosobjective-csavedevicensdocumentdirectory

Saving and retrieving information on device


This is a simple project that I am half copying from a book to teach myself. It's a to do list, with a table view, a text field and a button to add the task to the list. Then it saves the array of tasks to a directory (using a helper function) and when you close and reopen the application it retrieves the information. The thing runs on the computer and I thought it also worked on the device until I closed the app and reopened it to discover none of the elements of the array where there. As it works on the computer I have no idea what isn't right. Some of this code I understand, some I just copied for now (like the helper function), any suggestions greatly appreciated! P

Code:

h file

#import <UIKit/UIKit.h>

NSString *docPath();

@interface ViewController : UIViewController<UITableViewDataSource>

{
    UITableView *taskTable;
    UITextField *taskField;
    UIButton *insertButton;

    NSMutableArray *tasks;

}

- (void)addTask:(id)sender;

- (void)writeTasksToFile:(NSString *)path;

@end

m file

#import "ViewController.h"

NSString *docPath()
{
    NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

    return [[pathList objectAtIndex:0] stringByAppendingString:@"data.td"];
}

@interface ViewController ()

@end


@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
    if(plist) {
        tasks = [plist mutableCopy];
    } else {
        tasks = [[NSMutableArray alloc] init];
    }

    CGRect buttonFrame = CGRectMake(228,40,72,31);
    insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [insertButton setFrame:buttonFrame];
    insertButton.backgroundColor = [UIColor redColor];
    [insertButton addTarget:self action:@selector(addTask:) forControlEvents:UIControlEventTouchUpInside];
    [insertButton setTitle:@"Insert" forState:UIControlStateNormal];
    [[self view] addSubview:insertButton];

    CGRect tableFrame = CGRectMake(0, 80, 320, 380);
    taskTable = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStylePlain];
    [taskTable setSeparatorStyle:UITableViewCellSeparatorStyleNone];
    taskTable.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    [self.view addSubview:taskTable];
    [taskTable setDataSource:self];

    CGRect fieldFrame = CGRectMake(20, 40, 200, 31);
    taskField = [[UITextField alloc]initWithFrame:fieldFrame];
    [taskField setBorderStyle:UITextBorderStyleRoundedRect];
    [taskField setPlaceholder:@"type a task, enter"];
    [taskField setBackgroundColor:[UIColor greenColor]];
    [self.view addSubview:taskField];


    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];

}

- (void) applicationDidEnterBackground:(UIApplication *)application {
    [tasks writeToFile:docPath() atomically:YES];

}

- (void)addTask:(id)sender{

    NSString *t = [taskField text];

    if ([t isEqualToString:@""]) {return;}

    [tasks addObject:t];
    [taskTable reloadData];
    [taskField setText:@""];
    [taskField resignFirstResponder];

}



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

    return [tasks count];
}

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

{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        [tasks removeObjectAtIndex:indexPath.row];

        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    } 
}

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

    UITableViewCell *c = [taskTable dequeueReusableCellWithIdentifier:@"Cell"];

    if (!c){
        c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }

    NSString *item = [tasks objectAtIndex:[indexPath row]];
    [[c textLabel] setText:item];

    return c;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (void)writeTasksToFile:(NSString *)path
{
    [tasks writeToFile:path atomically:YES];
}

@end

edit------------------------------------------------------------------------------------------------------------------------------

Here is a debugger screenshot with a break point on the line that checks to see if there is a plist.

enter image description here


Solution

  • One thing I see that needs to be changed is that your docPath() is returning a bad path. You need to use stringByAppendingPathComponent instead of stringByAppendingString

    return [[pathList objectAtIndex:0] stringByAppendingPathComponent:@"data.td"];
    

    Or, if you want to use stringByAppendingString then it should be:

    return [[pathList objectAtIndex:0] stringByAppendingString:@"/data.td"];