Saving a Custom Object - RITAccess/accessmath GitHub Wiki
Note: this is done using both NSCoding, NSKeyedArchiver/NSKeyedUnarchiver, and NSUserDefaults.
Current properties (property name):
- name (itemName)
- date created (creationDate)
- associated lecture (associatedLecture)
- notes (notes)
- completed (completed)
NSCoding is the protocol reference used to encode and decode the instance variables of an object (in this case, Assignment Item). Upon calling this protocol, two methods must be declared in the .m file: initWithCoder: and encodeWithCoder:.
encodeWithCoder: instructs the object to encode its instance variables to the provided coder, and initWithCoder: instructs the object to initialize itself from the data in the provided coder. More information on the NSCoding protocol can be found in the Mac Developer Library: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSCoding_Protocol/
In the AssignmentItem.h file, the NSCoding protocol is implemented simply by including it between the angle brackets on the @interface line.
AssignmentItem.h
...
#import <Foundation/Foundation.h>
@interface AssignmentItem : NSObject <NSCoding>
@property NSString *itemName;
@property NSDate *creationDate;
@property NSString *associatedLecture;
@property NSString *notes;
@property BOOL completed;
...
Then - in the AssignmentItem.m file - the initWithCoder: and encodeWithCoder: methods are called to initialize and encode the properties of the AssignmentItem respectively.
AssignmentItem.m
#import "AssignmentItem.h"
@implementation AssignmentItem
static NSString* const assignmentName = @"assignment name";
static NSString* const associatedLecture = @"associated lecture";
static NSString* const associatedNotes = @"associated notes";
static NSString* const completed = @"completed";
static NSString* const dueDate = @"due date";
-(instancetype)initWithName:(NSString*)name Date:(NSDate*)creationDate Lecture:(NSString*)associatedLecture {
self.itemName = name;
self.creationDate = creationDate;
self.associatedLecture = associatedLecture;
self.notes = nil;
self.completed = NO;
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [self init];
if (self) {
self.itemName = [aDecoder decodeObjectForKey:assignmentName];
self.creationDate = [aDecoder decodeObjectForKey:dueDate];
self.associatedLecture = [aDecoder decodeObjectForKey:associatedLecture];
self.notes = [aDecoder decodeObjectForKey:associatedNotes];
self.completed = [aDecoder decodeBoolForKey:completed];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.itemName forKey:assignmentName];
[aCoder encodeObject:self.creationDate forKey:dueDate];
[aCoder encodeObject:self.associatedLecture forKey:associatedLecture];
[aCoder encodeObject:self.notes forKey:associatedNotes];
[aCoder encodeBool:self.completed forKey:completed];
}
Note that each variable is associated with a unique key so that it can be accurately initialized and encoded.
In this case, the custom objects being referred to are the students' assignments.
Saving the Assignments
The method to save the assignments is a class method, so that will not need to be instantiated beforehand in order to use it. This method is used to save each new assignment that the student creates as well as preserve their previous assignments.
+ (void)saveAssignment:(AssignmentItem*)assignment {
//Access the user defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//Access the data stored there for the given key
NSData *dataRepresentingSavedArray = [defaults objectForKey:@"saved array"];
//Initialize an NSMutableArray
NSMutableArray *arrayToSave = [[NSMutableArray alloc] init];
//If there is data previously saved for the given key, create a NSArray with it
//via NSKeyedUnarchiver and then add them to the new array
if (dataRepresentingSavedArray != nil) {
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
for (AssignmentItem *item in oldSavedArray) {
[arrayToSave addObject:item];
}
}
//Then add the newest assignment created by the student
[arrayToSave addObject:assignment];
//Using NSKeyedArchiver, archive the assignments saved to the array into data to be saved
NSData *encodedObjects = [NSKeyedArchiver archivedDataWithRootObject:arrayToSave];
//Lastly, store the encoded assignments in defaults with a unique key that can be called to unarchive it
[defaults setObject:encodedObjects forKey:@"saved array"];
[defaults synchronize];
}
Loading the Assignments
The loading method will be used to retrieve that data for the saved assignments for the students' use. This is also a class method.
+ (NSMutableArray*)loadAssignments {
//Access user defaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//Access the data saved in defaults for the given key
NSData *encodedObject = [defaults objectForKey:@"saved array"];
//Initialize a NSMutableArray via NSKeyedUnarchiver to unarchive the data back into the assignments
NSMutableArray *savedArray = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
//And return the array
return savedArray;
}