Ok, I've been over this a million times in the last week and I just am not getting it. (And yes, I've read Apple's docs.)
I am archiving my object and it appears to be archiving correctly (I can see the file written to the file system and if I examine it I can see my data within). However, when I relaunch my app my data is not being restored. Every example I read tells me how easy this is but I'm just not getting it. One unique thing is that my object is a singleton, it's used for passing data between view controllers.
I'd really appreciate some sage advice. Thanks in advance.
Here's my header:
#import <Foundation/Foundation.h>
#interface SharedAppDataObject : NSObject <NSCoding>
{
NSMutableDictionary *apiKeyDictionary;
NSString *skuFieldText;
NSIndexPath *checkmarkIndex;
}
+ (SharedAppDataObject *)sharedStore;
#property (nonatomic, copy) NSString *skuFieldText;
#property (nonatomic, copy) NSIndexPath *checkmarkIndex;
#property (nonatomic, copy) NSMutableDictionary *apiKeyDictionary;
-(void)setValue:(NSString *)apiKey forKey:(NSString *)name;
-(void)setSkuField:(NSString *)s;
-(void)setCheckmarkIndex:(NSIndexPath *)p;
-(NSMutableDictionary *)apiKeyDictionary;
-(BOOL)saveChanges;
#end
Here's my implementation:
#import "SharedAppDataObject.h"
#implementation SharedAppDataObject
#synthesize skuFieldText;
#synthesize checkmarkIndex;
#synthesize apiKeyDictionary;
//create our shared singleton store
+(SharedAppDataObject *)sharedStore {
static SharedAppDataObject *sharedStore = nil;
if (!sharedStore) {
sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];
if(!sharedStore)
sharedStore = [[super allocWithZone:NULL] init];
}
return sharedStore;
}
-(id) init {
self = [super init];
if (self) {
}
return self;
}
-(void)setValue:(id)apiKey forKey:(NSString *)name {
[apiKeyDictionary setObject:apiKey forKey:name];
}
-(void)setSkuField:(NSString *)s {
skuFieldText = s;
}
-(NSMutableDictionary *)apiKeyDictionary {
return apiKeyDictionary;
}
-(void)setCheckmarkIndex:(NSIndexPath *)p {
checkmarkIndex = p;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:skuFieldText forKey:#"skuFieldText"];
[aCoder encodeObject:checkmarkIndex forKey:#"checkmarkIndex"];
[aCoder encodeObject:apiKeyDictionary forKey:#"apiKeyDictionary"];
}
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
[self setSkuFieldText:[aDecoder decodeObjectForKey:#"skuFieldText"]];
[self setCheckmarkIndex:[aDecoder decodeObjectForKey:#"checkmarkIndex"]];
[self setApiKeyDictionary:[aDecoder decodeObjectForKey:#"apiKeyDictionary"]];
}
return self;
}
+(NSString *)archivePath {
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
return [documentDirectory stringByAppendingPathComponent:#"bbyo.archive"];
}
-(BOOL)saveChanges {
return [NSKeyedArchiver archiveRootObject:self toFile:[SharedAppDataObject archivePath]];
}
#end
Save method from App Delegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
BOOL success = [[SharedAppDataObject sharedStore] saveChanges];
if (success) {
NSLog(#"Saved all the data");
} else {
NSLog(#"Didn't save any of the data");
}
}
Initialize sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]]; in application:didFinishLaunchingWithOptions:. This method is used to initialize data structures and restore previous app state.
Also, take out static SharedAppDataObject *sharedStore = nil; from sharedStore. If the save file exists, [ShareAppDataObject sharedStore] will always unarchive the file which is not necessary. It can be unarchived once during initialization.
Here's a post that can answer your problem: http://bit.ly/PJO8fM
I cannot give you the answer but some ideas to figure this out. Taking this line:
sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];
So if the sharedStore is nil, something is wrong - so test for it. If nothing then log the path, and use NSFileManager methods to see if the file is there, its size etc. If you find the file is there and has size, but you cannot unarchive it, that's a problem of course. In that case, add special debug code just after you create the file:
-(BOOL)saveChanges {
BOO ret = [NSKeyedArchiver archiveRootObject:self toFile:[SharedAppDataObject archivePath]];
id foo = [NSKeyedUnarchiver unarchiveObjectWithFile:[SharedAppDataObject archivePath]];
// check if foo is not nil, if its the proper class, etc.
}
If when you save the file you can unarchive it just fine, but cannot on restart of the app, then something is wrong with the file. All this info should point the way to a solution.
Another thought - when you encode the data, log it, just to be sure its not nil - but even if so the unarchive should work.
Related
I have a very strange bug that I've bee trying to track down for several days. I'm saving state data for a game in a file in the app's Documents directory.
Everything had been working fine until a recent iOS update (not sure exactly when, somewhere around 9.0). Suddenly, data is not being archive / unarchived correctly.
The weird part is the code works fine when I run it from Xcode with the iPad tethered to my MAC or when in the emulator. When i download the app from the iTunes using TestFlight, it no longer works. This has made it extremely difficult to debug.
I've checked and double checked everything, I'm using the URL path, added error trapping code, etc. but archiving fails to work correctly when the app is installed from iTunes via TestFlight.
As a last resort I added new code that archives my object, immediately unarchives it into another variable, then display some data in a label. The resulting object contains null data.
No exceptions are thrown.
Just to reiterate, the code doesn't work ONLY when the app in installed from iTunes.
Here is the code snippet;
NSString *documentDirectory = [[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject] path];
NSString* filePath = [documentDirectory stringByAppendingPathComponent:#"playerTest.data"];
LBYPlayerData* pd1 = [[LBYPlayerData alloc ]init];
pd1.currentCountryID = 1;
pd1.lsn = #"123.456";
BOOL success = [NSKeyedArchiver archiveRootObject:pd1 toFile:filePath];
NSAssert(success, #"archiveRootObject failed");
LBYPlayerData* pd2 = nil;
#try {
pd2 = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
} #catch (NSException *exception) {
playerDataLabel.text = [NSString stringWithFormat:#"%#",exception.name];
playerUndoDataLabel.text = [NSString stringWithFormat:#"%#",exception.description];
} #finally {
NSAssert((pd2 != nil), #"archivePlayerDataUndo failed to unarchive");
playerDataLabel.text = [NSString stringWithFormat:#"path: %#",filePath];
playerUndoDataLabel.text = [NSString stringWithFormat:#"Undo Country:%li LSN:%#",(long)pd2.currentCountryID,pd2.lsn];
}
Here is the data model
//
// LBYPlayerData.h
#import <Foundation/Foundation.h>
#interface LBYPlayerData : NSObject
#property (nonatomic,readonly) BOOL isNewGame;
#property (nonatomic) NSInteger playerID;
#property (nonatomic) NSInteger usCardIdx;
#property (nonatomic) NSInteger drawDeckIdx;
#property (nonatomic) NSInteger discardDeckIdx;
#property (nonatomic) NSInteger removeDeckIdx;
#property (nonatomic) NSInteger currentCountryID;
#property (nonatomic) NSString* lsn;
#property (nonatomic) NSString* build;
#end
//
// LBYPlayerData.m
#import "LBYPlayerData.h"
#implementation LBYPlayerData
-(id)init
{
self = [super init];
_isNewGame = YES;
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
// NSLog(#"Saving Player Data");
_isNewGame = NO;
[aCoder encodeBool:_isNewGame forKey: NSStringFromSelector(#selector(isNewGame))];
[aCoder encodeInt64:_playerID forKey: NSStringFromSelector(#selector(playerID))];
[aCoder encodeInt64:_usCardIdx forKey: NSStringFromSelector(#selector(usCardIdx))];
[aCoder encodeInt64:_drawDeckIdx forKey: NSStringFromSelector(#selector(drawDeckIdx))];
[aCoder encodeInt64:_discardDeckIdx forKey: NSStringFromSelector(#selector(discardDeckIdx))];
[aCoder encodeInt64:_removeDeckIdx forKey: NSStringFromSelector(#selector(removeDeckIdx))];
[aCoder encodeInt64:_currentCountryID forKey: NSStringFromSelector(#selector(currentCountryID))];
[aCoder encodeObject:_lsn forKey: NSStringFromSelector(#selector(lsn))];
[aCoder encodeObject:_build forKey: NSStringFromSelector(#selector(build))];
// NSLog(#"Current Counry: %li",(long)_currentCountryID);
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
// NSLog(#"Loading Player Data");
self = [self init];
if (self) {
_isNewGame =[aDecoder decodeBoolForKey:NSStringFromSelector(#selector(isNewGame))];
[self setPlayerID :[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(playerID))]];
[self setUsCardIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(usCardIdx))]];
[self setDrawDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(drawDeckIdx))]];
[self setDiscardDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(discardDeckIdx))]];
[self setRemoveDeckIdx :[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(removeDeckIdx))]];
[self setCurrentCountryID:[aDecoder decodeIntegerForKey:NSStringFromSelector(#selector(currentCountryID))]];
[self setLsn :[aDecoder decodeObjectForKey :NSStringFromSelector(#selector(lsn))]];
[self setBuild :[aDecoder decodeObjectForKey :NSStringFromSelector(#selector(build))]];
}
return self;
}
#end
The problem was with NSAssert. I found code that was calling the function to archive the object within an NSAssert statement.
I need to take information submitted by a user, store that information in an NSMutableDictionary, then store that NSMutableDictionary inside another NSMutableDictionary which is then encoded inside another class. For whatever reason, I can't seem to store the first NSMutableDictionary inside of the other.
I had to slim down the code that's in here due to work rules, so sorry if it seems to be missing anything. I only posted the parts that I'm having trouble with.
UserInfo.h:
#import <Foundation/Foundation.h>
#interface MyPlanInfo : NSObject <NSCoding>
#property (nonatomic, strong) NSMutableDictionary *emergencyDictionary;
#end
UserInfo.m:
#import <Foundation/Foundation.h>
#import "MyPlanInfo.h"
static NSString *emergencyDictionaryKey = #"emergencyDictionaryKey";
#implementation MyPlanInfo
#synthesize emergencyDictionary;
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.emergencyDictionary forKey:emergencyDictionaryKey];
}
#end
infoView.h
#import <UIKit/UIKit.h>
#import "MyPlanInfo.h"
#interface infoView : UIViewController <NSCoding>
{
NSMutableDictionary *emergencyContactInfo;
NSArray *userInfo;
NSArray *userKeys;
NSMutableArray *tempArray;
}
#property (nonatomic, strong) MyPlanInfo *myPlanInfoObject;
-(void)saveUserInfo;
-(void)loadUserInfo;
#end
infoView.m:
#import "infoView.h"
#interface infoView ()
#end
#implementation infoView
static NSString *userInfoKey = #"userInfoKey";
static NSString *userName;
-(void)viewDidLoad
{
[super viewDidLoad];
if(!self.myPlanInfoObject)
{
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
}
[self loadUserInfo];
}
-(void)addToDictionary
{
emergencyContactInfo = [NSMutableDictionary dictionaryWithObjects:userInfo forKeys:userKeys];
if([userInfo count] != 0 || userInfo == nil)
{
self.myPlanInfoObject.emergencyDictionary = [NSMutableDictionary dictionaryWithObject:emergencyContactInfo forKey:userName];
}
[self saveUserInfo];
}
- (void)saveUserInfo
{
NSData *userInfoData = [NSKeyedArchiver archivedDataWithRootObject:self.myPlanInfoObject];
[[NSUserDefaults standardUserDefaults] setObject:userInfoData forKey:userInfoKey];
}
- (void)loadUserInfo
{
NSData *userInfoData = [[NSUserDefaults standardUserDefaults] objectForKey:userInfoKey];
if(userInfoData)
{
self.myPlanInfoObject = [NSKeyedUnarchiver unarchiveObjectWithData:userInfoData];
}
}
#end
In infoView.m, in the addToDictionary method, userInfo is an array of user inputted information, and userKey's is an array of key's. The emergencyContactInfo NSMutableDictionary works just fine, everything is in it, but when I try to set that as an object in a new NSMutableDictionary, for a key, it doesn't work. Everything is nil.
Anyone have any ideas on how what I'm doing wrong?
Edit: If you down vote, please leave a reason as to why so that I can avoid doing whatever I did wrong in the future.
In the following line you’re creating an instance of MyPlanInfo using plain alloc/init:
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
However, at least in the code provided, you haven’t overridden init in MyPlanInfo, but instead, initWithCoder::
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
When you use just plain init, the MyPlanInfo’s emergencyDictionary instance variable will be nil. You should likely add something like the following to MyPlanInfo to override init:
- (id) init
{
if ((self = [super init])) {
emergencyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
That will assure that the newly created MyPlanInfo instance has a proper NSMutableDictionary that can be manipulated from other classes.
I'm making a game using Cocos2d-iphone 2.1, and have encountered an error with NSCoding unarchiving implementation.
I've used the same pattern in my previous projects (made with UIKit), and everything worked perfetly. While when I'm implementing this pattern on cocos2d, it just doesn't work.
I have recreated the error on a sample project (which can be downloaded here https://www.dropbox.com/sh/30cyfczcxeyf8mr/uDcJiNYMdd ) and here's what I'm doing:
I've created a simple singleton class "GameStore".
Then I've created the "GameParameters" class which is a property of the singleton and conforms to NSCoding (therefore can be archived).
In that class there's the "highscore" property of type int (for example) which I'd like to keep archived as a high score value.
In the GameStore class I initialize the GameParameters instance for the first time, if there's an archived object - I unarchive it.
In the "HelloWorldLayer" (which is a default cocos2d placeholder class) I call NSLog to display the "highscore" value and then set it to a new value
In AppDelegate I call the "save data" method to archive data whenever the home button is pressed.
That's it.
When I start the app for the first time, everything works well, and I save the data by pressing the home button.
And when I start the app again, I run into random (as it seems) EXT_BAD_ACCESS errors... Sometimes when I'm getting the highscore value, sometimes when archiving it again.
Any idea what I might be doing wrong here?
Thanks!
GameStore class
Header file:
#import <Foundation/Foundation.h>
#class GameParameters;
#interface GameStore : NSObject
#property (retain, nonatomic) GameParameters * parameters;
+ (GameStore *) game;
- (void) saveData;
#end
Implementation file:
#import "GameStore.h"
#import "GameParameters.h"
static GameStore * game = nil;
#implementation GameStore
#synthesize parameters;
+ (GameStore *) game
{
if (!game) game = [[super allocWithZone:nil] init];
return game;
}
- (id) init
{
if (game != nil) {
return game;
}
self = [super init];
if (self) {
// Initialization
// Try and load the "GameParameters" from archive
parameters = [NSKeyedUnarchiver unarchiveObjectWithFile:[self archivePath]];
NSLog(#"Highscore: %i",parameters.highscore);
// If there's no archive, initialize the "GameParameters"
if (!parameters) {
parameters = [[GameParameters alloc] init];
parameters.highscore = 12345;
}
}
return self;
}
- (void) saveData
{
[NSKeyedArchiver archiveRootObject:parameters toFile:[self archivePath]];
NSLog(#"Data saved");
}
- (NSString *)archivePath
{
NSArray * documentDirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentDir = [documentDirs objectAtIndex:0];
return [documentDir stringByAppendingPathComponent:#"hs.archive"];
}
#end
GameParameters class
Header file:
#import <Foundation/Foundation.h>
#interface GameParameters : NSObject <NSCoding>
#property (nonatomic, assign) int highscore;
#end
Implementation file:
#import "GameParameters.h"
#implementation GameParameters
#synthesize highscore;
- (id) initWithCoder:(NSCoder *)aDecoder
{
highscore = [aDecoder decodeIntForKey:#"1"];
return self;
}
- (void) encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeInt:highscore forKey:#"1"];
}
#end
So here is my problem. I am trying to archive an array of objects and when I unarchive them although the count is the same and the objects inside the root object are the same it does not find the specified object in the unarchived array.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"self.vendors.count = %d", self.vendors.count);
[NSKeyedArchiver archiveRootObject:self.vendors toFile:[self vendorsArchivePath]];
NSMutableArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:[self
vendorsArchivePath]];
NSLog(#"array.count = %d", array.count);
NSLog(#"%d", [self.vendors indexOfObject:self.vendors[indexPath.row]]);
NSLog(#"%d", [array indexOfObject:self.vendors[indexPath.row]]);
}
In order to troubleshoot myself; I have the counts of both arrays listed and at the bottom and the index of the object in each array in an NSLog.
Here is the log...
2014-04-27 12:53:04.813 Inventory[12272:907] self.vendors.count = 5
2014-04-27 12:53:04.827 Inventory[12272:907] array.count = 5
2014-04-27 12:53:04.828 Inventory[12272:907] 0
2014-04-27 12:53:04.831 Inventory[12272:907] 2147483647
So my question is: Why in the world is the last NSLog not finding the same object, that I archived and unarchived in the SAME function not being found in the array? Are objects modified when archived and unarchived? Or is there something else that I am missing.
EDIT: Here are my vendor.h and vendor.m files:
//vendor.h
#import <Foundation/Foundation.h>
#interface SELVendor : NSObject <NSCoding>
#property (nonatomic) NSMutableArray *itemsAvailable;
#property (nonatomic) NSString *name;
#property (nonatomic) NSString *phoneNumber;
#property (nonatomic) NSString *email;
#property (nonatomic) NSString *vendorKey;
#end
//vendor.m
#import "SELVendor.h"
#implementation SELVendor
-(instancetype) init {
self = [super init];
if (self) {
self.name = #"Unnamed Vendor";
self.itemsAvailable = [[NSMutableArray alloc] init];
NSUUID *uuid = [[NSUUID alloc] init];
self.vendorKey = [uuid UUIDString];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.name forKey:#"name"];
[aCoder encodeObject:self.itemsAvailable forKey:#"itemsAvailable"];
[aCoder encodeObject:self.phoneNumber forKey:#"phoneNumber"];
[aCoder encodeObject:self.email forKey:#"email"];
[aCoder encodeObject:self.vendorKey forKey:#"vendorKey"];
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:#"name"];
self.itemsAvailable = [aDecoder decodeObjectForKey:#"itemsAvailable"];
self.phoneNumber = [aDecoder decodeObjectForKey:#"phoneNumber"];
self.email = [aDecoder decodeObjectForKey:#"email"];
self.vendorKey = [aDecoder decodeObjectForKey:#"vendorKey"];
}
return self;
}
#end
This means that the object wasn't found 2147483647 == NSNotFound
What you're trying to do is save a array of objects, and then read them back out to a varaible. Doing this will create (alloc/init) the objects again so they won't occupy the same location in memory. Depending on how you implement your encoder/decode methods, the object might be exactly the same as the other one (content wise). What you need to do is override isEqual: (and hash) in your class and check the objects in there.
If you're objects have some kind of ID property you can just do:
-(BOOL)isEqual:(id)object
{
if (self == object) {
return YES;
}
if (![object isKindOfClass:[self class]]) {
return NO;
}
return [self.ID isEqual:object.ID];
}
If none of your properties on your object are unique, you can check each one in the isEqual: method.
See this answer for more info.
indexOfObject: uses isEqual: to test whether an object in the array is the "same" as the object you're looking for. When you archive and unarchive an object, the resulting object is not at the same memory address (it is effectively a copy of the original object).
Since the default implementation of isEqual: return YES only for the same object (memory address), this explains the behavior you're seeing. You probably want to override isEqual: (and hash, which you should usually override if you override isEqual:) to check whatever member variables are important for your notion of equality. (Or you can use one of a zillion libraries out there that make this easier, such as Mantle.)
I have class for playing sound in app.
I implemented on/off switch(on GUI), for disabling and enablining sound play.
I am using BOOL property for that and this is working.
Now I am trying to implement saving that BOOL (is sound on/off) in file so that next time when app is started state is automatically restored.
For that I am using NSCoding protocol, archiving is working but I have problem with unarchiving.
My app will not start it will just show black screen.
This is my code, only part that I think it is important.
GTN_Sound.h
#import <Foundation/Foundation.h>
#import <AudioToolbox/AudioToolbox.h> // for playing sound
#interface GTN_Sound : NSObject <NSCoding>
#property(nonatomic, readwrite, unsafe_unretained) BOOL isSoundOn;
+ (id)sharedManager;
- (void)playWinSound;
- (void)playLoseSound;
#end
GTN_Sound.m
#pragma mark - NSCoding Methods
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeBool:self.isSoundOn forKey:#"isSoundOn"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [GTN_Sound sharedManager];
if (self) {
_isSoundOn = [aDecoder decodeBoolForKey:#"isSoundOn"];
}
return self;
}
I think that code is so far so good ?
Continuation of GTN_Sound.m
#pragma mark - itemArchivePath Method
- (NSString *)itemArchivePath
{
// Make sure that the first argument is NSDocumentDirectory
// and not NSDocumentationDirectory
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
// Get the one document directory from that list
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:#"sound.archive"];
}
#pragma mark - custom seter Method
- (void)setIsSoundOn:(BOOL)theBoolean {
NSLog(#"My custom setter\n");
if(_isSoundOn != theBoolean){
_isSoundOn = theBoolean;
NSString *path = [self itemArchivePath];
[NSKeyedArchiver archiveRootObject:self toFile:path]; // this is doing save
}
}
It is done that for every time when switch on GUI is changed I do the savings.
This look fine from my side, because I am not expecting that user will change this many times.
Now the unarchiving comes and I thin that here are some problems.
#pragma mark - Singleton Methods
+ (id)sharedManager {
static GTN_Sound *sharedMyManager = nil;
// to be thread safe
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] initPrivate];
});
return sharedMyManager;
}
- (instancetype)init
{
#throw [NSException exceptionWithName:#"Singleton"
reason:#"Use +[GTN_Sound sharedManager]"
userInfo:nil];
return nil;
}
// Here is the real (secret) initializer
- (instancetype)initPrivate
{
self = [super init];
if (self) {
NSString *path = [self itemArchivePath]; // do as iVar, for futture
self = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
//_isSoundOn = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
return self;
}
I think that problem is in this line
self = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
But have no idea how to fix it.
I have read that when I am doing archiving, that I need to archive all properties of object.
Does this apply to private ivars also ?
Any help is appreciated.
Thanks
You can only archive NSObject inheriting objects. ie. NSNumber
[NSKeyedArchiver archiveRootObject:#YES toFile:path]; //to save
_isSoundOn = [[NSKeyedUnarchiver unarchiveObjectWithFile:path] boolValue]; //to load