如何使用当前设置保存iPhone应用程序的文件?

时间:2014-03-27 15:53:55

标签: ios objective-c storage

我不能为我的生活弄清楚如何使用我当前的设置保存我的数据!我试过使用NSUserDefaults,但因为我使用自定义对象它不起作用。我一直在试图弄清楚如何使用NSKeyedArchiver,但我无法弄清楚在哪里实现它。

AG_AddItemViewController.h

#import <UIKit/UIKit.h>
#import "AG_Storage.h"

@interface AG_AddItemViewController : UIViewController

@property AG_Storage *store;


@end

AG_AddItemViewController.m

#import "AG_AddItemViewController.h"

@interface AG_AddItemViewController()

@property(weak,nonatomic)IBOutlet UITextField *textField;
@property(weak,nonatomic)IBOutlet UIButton *doneButton;
@property IBOutlet UIDatePicker *datePicker;
@property NSMutableArray *defaultsArray;

@end

@implementation AG_AddItemViewController


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


    if (sender != self.doneButton) return;

    if (self.textField.text.length > 0) {
        self.store =[[AG_Storage alloc] init];
        self.store.itemName = self.textField.text;
        self.store.completed = NO;

        NSDate *dateChosen = self.datePicker.date;
        self.store.creationDate = dateChosen;
        NSLog(@"%@", self.store);

        [self.defaultsArray addObject:self.textField.text];
    }

}


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.defaultsArray = [[NSMutableArray alloc] init];

}

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


@end

AG_Storage

#import <Foundation/Foundation.h>

@interface AG_Storage : NSObject

@property NSString *itemName;
@property BOOL *completed;
@property NSDate *creationDate;
@property NSDate *todaysDate;

@end

AG_ViewController.h

#import <UIKit/UIKit.h>

@interface AG_ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{

    IBOutlet UITableView *tableView;
    IBOutlet UILabel *todaysDate;
    IBOutlet UILabel *subtractDate;
    IBOutlet UILabel *addDate;
}
@end

AG_ViewController.m

#import "AG_ViewController.h"
#import "AG_Storage.h"
#import "AG_AddItemViewController.h"

@interface AG_ViewController ()

@property NSMutableArray *mainArray;
@property NSMutableArray *yesterdayArray;
@property NSMutableArray *tomorrowArray;
@property NSDate *todayDate;
@property NSDate *tomorrowsDate;
@property NSDate *yesterdaysDate;

@end

@implementation AG_ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.mainArray = [[NSMutableArray alloc] init];
    self.yesterdayArray = [[NSMutableArray alloc]init];
    self.tomorrowArray = [[NSMutableArray alloc]init];
    [self loadInitialData];
}

- (void)loadInitialData
{
    // Do any additional setup after loading the view, typically from a nib.




    //NSDate Info

    NSTimeInterval secondsPerDay = 24 * 60 * 60;
    NSDate *today = [[NSDate alloc]init];
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"MMMM dd, yyyy"];

    self.todayDate = today;
    self.tomorrowsDate = [today dateByAddingTimeInterval: secondsPerDay];
    self.yesterdaysDate = [today dateByAddingTimeInterval: -secondsPerDay];

    NSString *todayString = [dateFormat stringFromDate:self.todayDate];
    NSString *tomorrowString = [dateFormat stringFromDate:self.tomorrowsDate];
    NSString *yesterdayString = [dateFormat stringFromDate:self.yesterdaysDate];

    todaysDate.text = todayString;
    addDate.text = tomorrowString;
    subtractDate.text = yesterdayString;

    AG_Storage *theDateToday = [[AG_Storage alloc]init];
    theDateToday.todaysDate = self.todayDate;


    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults arrayForKey:todayString];
    NSLog(@"Tried to load...");
    [defaults synchronize];



}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return [self.mainArray count];
}


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

    UITableViewCell *cell = [tableViewer dequeueReusableCellWithIdentifier:@"thisCell"];
    AG_Storage *toDoItem = [self.mainArray objectAtIndex:indexPath.row];
    cell.textLabel.text = toDoItem.itemName;



    if (toDoItem.completed) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else{
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;

}



- (IBAction)unwindToList:(UIStoryboardSegue *)segue
{

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"MMMM dd, yyyy"];

    AG_AddItemViewController *source = [segue sourceViewController];
    AG_Storage *item = source.store;

    NSDate *dateCreated = item.creationDate;



    NSString *todayString = [dateFormat stringFromDate:self.todayDate];
    NSString *dateCreatedString = [dateFormat stringFromDate:dateCreated];
    NSString *tomorrowString = [dateFormat stringFromDate:self.tomorrowsDate];
    NSString *yesterdayString = [dateFormat stringFromDate:self.yesterdaysDate];


    //Set up file storage!

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];


    if (item.itemName != nil) {

        if ([dateCreatedString isEqualToString:todayString]) {
            [self.mainArray addObject:item];
            [tableView reloadData];

            [defaults setObject:self.mainArray forKey:todayString];
            [defaults synchronize];
            NSLog(@"Saved");




        }
        else if ([dateCreatedString isEqualToString:tomorrowString]){
            [self.tomorrowArray addObject:item];
            [tableView reloadData];

            NSLog(@"THIS WORKED TOO :D");
        }
        else if ([dateCreatedString isEqualToString:yesterdayString]){
            [self.yesterdayArray addObject:item];
            [tableView reloadData];

            NSLog(@"THIS WORKED");
        }
        else{

        }
    }
}

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


#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableViewer didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableViewer deselectRowAtIndexPath:indexPath animated:NO];
    AG_Storage *tappedItem = [self.mainArray objectAtIndex:indexPath.row];
    tappedItem.completed = !tappedItem.completed;
    [tableViewer reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];

}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return YES if you want the specified item to be editable.
    return YES;
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableViews commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.mainArray removeObjectAtIndex:indexPath.row];
        [tableViews deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

@end

我想使用NSUserDefaults,因为它看似简单,但如果我不能那样。我出于某种原因无法绕过这个。

编辑:这就是我尝试实现Hyperbole的想法......

if (item.itemName != nil) {

        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:item];

        [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"storageObjectKey"];
        [[NSUserDefaults standardUserDefaults] synchronize];

        if ([dateCreatedString isEqualToString:todayString]) {
            [self.mainArray addObject:item];
            [tableView reloadData];

            NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"storageObjectKey"];
            AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];



            NSLog(@"%@", someStorageObject);


            NSLog(@"Saved");


        }

1 个答案:

答案 0 :(得分:0)

我的建议是让AG_Storage声明符合NSSecureCoding协议,并在那里实现编码方法。完成之后,将AG_Storage个对象放入NSUserDefaults是一项微不足道的任务。

@interface AG_Storage : NSObject <NSSecureCoding>

@end

@implementation AG_Storage

+ (BOOL)supportsSecureCoding {

    return YES;
}

- (void)encodeWithCoder:(NSCoder *)encoder {

    [encoder encodeObject:self.itemName forKey:@"itemNameKey"];
    [encoder encodeObject:@(self.completed) forKey:@"completedKey"];
    [encoder encodeObject:self.creationDate forKey:@"creationDateKey"];
    [encoder encodeObject:self.todaysDate forKey:@"todaysDateKey"];  // This one doesn't seem necessary to save, though I'm sure you would know better than I would.
}

- (id)initWithCoder:(NSCoder *)decoder {

    if ([decoder respondsToSelector:@selector(decodeObjectOfClass:forKey:)])    // Secure coding is only available in iOS 6
    {
        self.itemName = [decoder decodeObjectOfClass:[NSString class] @"itemNameKey"];
        self.completed = [[decoder decodeObjectOfClass:[NSNumber class] forKey:@"completedKey"] boolValue];
        self.creationDate = [decoder decodeObjectOfClass:[NSDate class] forKey:@"creationDateKey"];
        self.todaysDate = [decoder decodeObjectOfClass:[NSDate class] forKey:@"todaysDateKey"];
    }
    else
    {
        self.itemName = [decoder decodeObjectForKey:@"itemNameKey"];
        self.completed = [[decoder decodeObjectForKey:@"completedKey"] boolValue];
        self.creationDate = [decoder decodeObjectForKey:@"creationDateKey"];
        self.todaysDate = [decoder decodeObjectForKey:@"todaysDateKey"];
    }

@end

下一步是将其分解为NSData的实例,以便存储在NSUserDefaults中:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:someAG_StorageObject];

[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"storageObjectKey"];
[[NSUserDefaults standardUserDefaults] synchronize];

稍后检索它:

NSData *data = [[NSUserDefaults standardDefaults] objectForKey:@"storageObjectKey"];
AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:savedData];