How to use NSUserDefaults to save data from ViewController and retrieve it to TableViewController when app reruns

StackOverflow https://stackoverflow.com/questions/23520859

Question

I'm desperate, been solving this for hours.. So I have a class "WishListItem", a TableViewController and a ViewController. I'm having difficulties in saving chunk of data and retrieving it from TableViewController? How to do this effectively?

I'm going to paste all my codes because I don't know if there something important that must be included to my question. So I'm sorry, please bear with me. Here it is.

ViewController.h:

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

@interface JLSViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIBarButtonItem *addWishListButton;
@property (strong, nonatomic) IBOutlet UITextField *wishTextField;
@property (strong, nonatomic) IBOutlet UITextField *descTextField;
@property (strong, nonatomic) IBOutlet UIDatePicker *targetDatePicker;

@property WishlistItem *wishItem;

@end

ViewController.m

#import "JLSViewController.h"
#import "WishlistTableViewController.h"

@interface JLSViewController ()

@property NSMutableArray *wishlistItem;

@end

@implementation JLSViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

}

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

    NSDate *myDate = self.targetDatePicker.date;
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"MMM d, YYYY"];
    NSString *prettyVersion = [dateFormat stringFromDate:myDate];

    if (sender != self.addWishListButton) return;
    if (self.wishTextField.text.length > 0) {
        self.wishItem = [[WishlistItem alloc] init];
        self.wishItem.wishlistItem  = self.wishTextField.text;
        self.wishItem.descWishItem = self.descTextField.text;
        self.wishItem.targetDate = prettyVersion;
    }
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:self.wishItem.wishlistItem forKey:@"itemWish"];
    [defaults setObject:self.wishItem.descWishItem forKey:@"itemDesc"];
    [defaults setObject:self.wishItem.targetDate forKey:@"itemDate"];
    [defaults synchronize];
}

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

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
    [super touchesBegan:touches withEvent:event];
}

@end

TableViewController.h

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

@interface WishlistTableViewController : UITableViewController

- (IBAction)unwindToWishlistTableViewController:(UIStoryboardSegue *)unwindSegue;


@property NSMutableArray *wishlistItem;


@end

TableViewController.m

#import "WishlistTableViewController.h"
#import "WishlistItem.h"
#import "JLSViewController.h"
#import "DetailViewController.h"

@interface WishlistTableViewController ()



@end

@implementation WishlistTableViewController


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

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.wishlistItem = [[NSMutableArray alloc]init];


}

- (IBAction)unwindToWishlistTableViewController:(UIStoryboardSegue *)unwindSegue {

    JLSViewController *source = [unwindSegue sourceViewController];
    WishlistItem *item = source.wishItem;
    if (item != nil) {
        [self.wishlistItem addObject:item];
        [self.tableView reloadData];
    }
}

- (IBAction)delete:(id)sender {

}

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

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    //#warning Potentially incomplete method implementation.
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //#warning Incomplete method implementation.
    // Return the number of rows in the section.
    return [self.wishlistItem count];
}


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

    static NSString *cellIdentifier = @"wishlistCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    WishlistItem *wish = [self.wishlistItem objectAtIndex:indexPath.row];

    // Configure the cell...
    //Set target date string
    NSString *targetDate = [NSString stringWithFormat:@"Target Date: %@", wish.targetDate];

    //Set wishlist item string
    NSString *wishItemString = wish.wishlistItem;

    cell.textLabel.text = wishItemString;
    cell.detailTextLabel.text = targetDate;

    return cell;
}

/*
 #pragma mark - Navigation

 // In a storyboard-based application, you will often want to do a little preparation before navigation
 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
 {
 // Get the new view controller using [segue destinationViewController].
 // Pass the selected object to the new view controller.
 }
 */

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

    WishlistItem *wish = [self.wishlistItem objectAtIndex:indexPath.row];
    DetailViewController *dvc = [self.storyboard instantiateViewControllerWithIdentifier:@"dvcID"];

    dvc.wishItemStr = wish.wishlistItem;
    dvc.dateItemStr = wish.targetDate;
    dvc.descItemStr = wish.descWishItem;


    [self.navigationController pushViewController:dvc animated:YES];
}




// Delete row/cell
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove the row from data model
    [self.wishlistItem removeObjectAtIndex:indexPath.row];

    // Request table view to reload
    [tableView reloadData];
}

@end

From my ViewController, i want to save every entries that's being added and retrieve it later to my TableViewController. Thank you and I'm really sorry for posting all my codes because I'm really frustrated already, been solving this for several hours. Thank you in advance.

I've used NSUserDefaults in my prepareForSegue. But I think I can't retrieve it properly from my TableViewController.

I've included my "Saving Data" only using NSUserDefaults because I don't know how I will implement the "Loading Data" to my TableViewController.

I'm sorry for my code. Just a beginner for now.

My only goal is just to save my 3 strings(Wish Item, Wish Description, Target Date) and I just want to retrieve those data every time the app reruns..

Was it helpful?

Solution 2

@Rhenzzz : you have to replace this

cell.textLabel.text = wishItemString; 
cell.detailTextLabel.text = targetDate;

by

cell.textLabel.text = itemWish ; 
cell.detailTextLabel.text = itemDate;

in Jay's code.

OTHER TIPS

-(void)yourSaveMethod
 { 
   NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
   [defaults setValue:@"My saved Data" forKey:@"infoString"];
 }

 -(void)yourLoadMethod
 {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    cell.tableview.text = [defaults objectForKey:@"infoString"];
 }``

To save your array state use this ie in view controller

NSString *valueToSave = @"someValue";
[[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"preferenceName"];
[[NSUserDefaults standardUserDefaults] synchronize];

use this where you want to retrieve the variable ie. intableViewController

 NSString *savedValue = [[NSUserDefaults standardUserDefaults]
            stringForKey:@"preferenceName"];

I would recommend Core Data for this as well.

However, if you really wanted to use NSUserDefaults you should keep an NSArray of NSDictionarys in a single key. The way you're doing things now, you would only be able to display one item in your UITableView at a time because you overwrite the same keys each time you prepareForSegue.

Put this in a separate header file and import in where necessary:

#define WISH_ITEMS_KEY @"wishItems"

Execute this code once (possibly in the AppDelegate like so):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults registerDefaults:@{WISH_ITEMS_KEY: @[]}];
    [defaults synchronize];
    return YES;
}

Then in your prepareForSegue:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *wishItems = [[defaults arrayForKey:WISH_ITEMS_KEY] mutableCopy];
[wishItems addObject:@{@"itemWish": self.wishItem.wishlistItem,
                       @"itemDesc": self.wishItem.descWishItem,
                       @"itemDate": self.wishItem.targetDate}];
[defaults setObject:wishItems forKey:WISH_ITEMS_KEY];
[defaults synchronize];

In your TableViewController's viewDidLoad:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.wishlistItem = [[defaults arrayForKey:WISH_ITEMS_KEY] mutableCopy];

Then in your cellForRowAtIndexPath you can retrieve each item and set your cell:

NSDictionary *itemDictionary = self.wishlistItem[indexPath.row];
NSString *itemWish = itemDictionary[@"itemWish"];
NSString *itemDesc = itemDictionary[@"itemDesc"];
NSString *itemDate = itemDictionary[@"itemDate"];

Hope that helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top