I am developing an application where the user creates an event which has 3 fields:
Category , name , event. After the user gives his entry , i have a save button that will save his data for future reference. Then when he opens the app again the data will be shown in a table View.
How exactly do i "save" data on iOS ? I know about the NSUserDefaults , but i am pretty sure this is not the way for this example.
What i ve done so far :
I created a "Note" class with Category , name , event.
The code for my save button looks like this:
- (IBAction)save:(id)sender {
//creating a new "note" object
Note *newNote = [[Note alloc]init];
newNote.category = categoryField.text;
newNote.name = nameField.text;
newNote.event = eventField.text;
// do whatever you do to fill the object with data
NSData* data = [NSKeyedArchiver archivedDataWithRootObject:newNote];
/*
Now we create the path to the documents directory for your app
*/
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
/*
Here we append a unique filename for this object, in this case, 'Note'
*/
NSString* filePath = [documentsDirectory stringByAppendingString:@"Note"];
/*
Finally, let's write the data to our file
*/
[data writeToFile:filePath atomically:YES];
/*
We're done!
*/
}
Is this the correct way to save an event? How can i retrieve now what i wrote ?
Secondly if i run this code again i ll overwrite data , or create new entry?
I would like to see how i can make a new entry every time.
Also i would like to delete an event from the table that i am presenting them , so i would like to see how the delete would work.
My "Note" object looks like that:
@interface Note : NSObject <NSCoding> {
NSString *category;
NSString *name;
NSString *event;
}
@property (nonatomic, copy) NSString *category;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *event;
@end
Try
//Note.h
#define kNoteCategory @"Category"
#define kNoteName @"Name"
#define kNoteEvent @"Event"
@interface Note : NSObject
@property (nonatomic, copy) NSString *category;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *event;
- (id)initWithDictionary:(NSDictionary *)dictionary;
+ (NSArray *)savedNotes;
- (void)save;
//Note.m file
- (id)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self)
{
self.category = dictionary[kNoteCategory];
self.name = dictionary[kNoteName];
self.event = dictionary[kNoteEvent];
}
return self;
}
+ (NSString *)userNotesDocumentPath
{
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"UserNotes.plist"];
return documentsPath;
}
+ (NSArray *)savedNotes
{
NSString *documentsPath = [self userNotesDocumentPath];
NSArray *savedNotes = [NSArray arrayWithContentsOfFile:documentsPath];
NSMutableArray *savedUserNotes = [@[] mutableCopy];
for (NSDictionary *dict in savedNotes) {
Note *note = [[Note alloc]initWithDictionary:dict];
[savedUserNotes addObject:note];
}
return savedUserNotes;
}
- (NSDictionary *)userNoteDictionary
{
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
if (self.category) {
dict[kNoteCategory] = self.category;
}
if (self.name) {
dict[kNoteName] = self.name;
}
if (self.event) {
dict[kNoteEvent] = self.event;
}
return dict;
}
- (void)saveUserNotesToPlist:(NSArray *)userNotes
{
NSMutableArray *mutableUserNotes = [@[] mutableCopy];
for (Note *note in userNotes) {
NSDictionary *dict = [note userNoteDictionary];
[mutableUserNotes addObject:dict];
}
NSString *documentsPath = [Note userNotesDocumentPath];
[mutableUserNotes writeToFile:documentsPath atomically:YES];
}
#pragma mark - Save
- (void)save
{
NSMutableArray *savedNotes = [[Note savedNotes] mutableCopy];
[savedNotes addObject:self];
[self saveUserNotesToPlist:savedNotes];
}
Save a note by
- (IBAction)save:(id)sender {
//creating a new "note" object
Note *newNote = [[Note alloc]init];
newNote.category = categoryField.text;
newNote.name = nameField.text;
newNote.event = eventField.text;
//Saves the note to plist
[newNote save];
//To get all saved notes
NSArray *savedNotes = [Note savedNotes];
}
Source Code
You can use NSKeyedUnArchiver to retrieve the data. It will over write if you try to write in the same file path
You can use core data to save all your data and delete it when you want. The code above always create new object of Note class so every time new data you have but when you will try to write with the same name "Note". It always overwrite the old data.
All are correct besides that you can use Sqlite to save the data locally with your application.
This is just a file but accepts all standard sql statements.
This is also one way to save the data locally..
For saving data via NSUserDefaults I'm using GVUserDefaults
Usage
Create a category on GVUserDefaults, add some properties in the .h file and make them @dynamic in the .m file.
// .h
@interface GVUserDefaults (Properties)
@property (nonatomic, weak) NSString *userName;
@property (nonatomic, weak) NSNumber *userId;
@property (nonatomic) NSInteger integerValue;
@property (nonatomic) BOOL boolValue;
@property (nonatomic) float floatValue;
@end
// .m
@implementation GVUserDefaults (Properties)
@dynamic userName;
@dynamic userId;
@dynamic integerValue;
@dynamic boolValue;
@dynamic floatValue;
@end
Now, instead of using [[NSUserDefaults standardUserDefaults] objectForKey:@"userName"]
, you can simply use [GVUserDefaults standardUserDefaults].userName
.
You can even save defaults by setting the property:
[GVUserDefaults standardUserDefaults].userName = @"myusername";
Look, I am giving you the General Idea, you can use this code according to your requirement.
1) Get the "Path" of yourPlist.plist
file :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourPlist.plist"];
2) Insert data into the yourPlist :
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:categoryField.text forKey:@"Category"];
[dict setValue:nameField.text forKey:@"Name"];
[dict setValue:eventField.text forKey:@"Event"];
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObject:dict];
[arr writeToFile: path atomically:YES];
3) Retrieve data from the yourPlist :
NSMutableArray *savedStock = [[NSMutableArray alloc] initWithContentsOfFile: path];
for (NSDictionary *dict in savedStock) {
NSLog(@"my Note : %@",dict);
}