can't figure out why archiveRootObject is failing to write file - iphone

this seems to work fine in the simulator but on the device the files are not being written.
here's the code.
-(void)saveOld{
NSArray *saveState = [NSArray arrayWithObjects:headArray,dropQArray,[NSNumber numberWithInt:dropLimit],[NSNumber numberWithInt:dropCount],[NSNumber numberWithInt:score],[NSNumber numberWithInt:level],[NSNumber numberWithInt:maxChain],nil];
NSMutableString *path = [[NSHomeDirectory() mutableCopy]autorelease];
[path appendString:#"/saveState"];
BOOL saved = [NSKeyedArchiver archiveRootObject:saveState toFile:path];
NSLog(#"did save state %d",saved);
path = [[NSHomeDirectory() mutableCopy]autorelease];
[path appendString:#"/isSaveState"];
saved = [NSKeyedArchiver archiveRootObject:[NSNumber numberWithBool:1] toFile:path];
NSLog(#"did save state %d",saved);
}

There is no home directory on the iPhone :D
You should use this instead:
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
This will give you the basic documents directory, append strings to it then.

Related

I'm making an app involving saving data to a textfield and loading it back. It's working in the simulator but not in on my actual iPhone. Why so?

In the program I use this method to create a file in which I can save:
-(NSString*) saveFilePath{
NSString* path = [NSString stringWithFormat:#"%#%#",
[[NSBundle mainBundle] resourcePath],
#"savingfile.plist"];
return path;}
Then I used a button to initiate the process of putting the data into the file (I first put it all into an array so that it would be easier.):
- (IBAction)save
{
NSMutableArray *myArray = [[NSMutableArray alloc] init];
[myArray addObject:name.text];
[myArray addObject:position.text];
[myArray addObject:cell.text];
[myArray addObject:office.text];
[myArray addObject:company.text];
[myArray writeToFile:[self saveFilePath] atomically:YES];
}
Finally, I loaded the information back into the textfields in the - (void)viewDidAppear method.
- (void)viewDidAppear:(BOOL)animated
{
NSMutableArray* myArray = [NSMutableArray arrayWithContentsOfFile:[self saveFilePath]];
name.text = [myArray objectAtIndex:0];
position.text = [myArray objectAtIndex:1];
cell.text = [myArray objectAtIndex:2];
office.text = [myArray objectAtIndex:3];
company.text = [myArray objectAtIndex:4];
}
For some reason, on the simulator it's working perfectly on the simulator, but not working at all when I try to run on my physical iPhone.
I think you're trying to save to a location that's read-only on iOS. It works on the simulator because the simulator doesn't totally replicate the sandboxing environment on the actual hardware.
Rather than saving to the resourcesPath you should be saving your files to the Documents directory (or the cache directory, if appropriate).
You can get a path to the documents directory as follows:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
There's more information at this question here: How to save file in resource folder of an app in Objective-c

Cocoa Error 513 when trying to write to normal directories

I'm simply trying to create a secure user file that will save basic login information so it does not need to be typed in every time the app launches. I know I cannot write to the bundle, so I am trying one of the other directories we are supposed to have access to, like caches, documents, and library, none of these have resulted in a successful write
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, NO);
NSString *cacheDirectory = [paths objectAtIndex:0];
NSLog(#"Found cache directory: %#", cacheDirectory);
NSString *fileName = [cacheDirectory stringByAppendingPathComponent:#"987f065e4656dba6c"];
NSString *userData = [[NSString alloc] initWithFormat:#"%#\n%#\n%#", owner.schoolWebsite.text, owner.username.text, owner.password.text];
NSError *fileError = nil;
if(!([[NSFileManager defaultManager] createDirectoryAtPath:cacheDirectory withIntermediateDirectories:YES attributes:nil error:&fileError]))
{
NSLog(#"Error creating cache directory: %#\n%#\n%#\n%#", [fileError localizedDescription], [fileError localizedFailureReason], [fileError localizedRecoveryOptions], [fileError localizedRecoverySuggestion]);
}
if (!([[NSFileManager defaultManager] createFileAtPath:fileName contents:[userData dataUsingEncoding:NSASCIIStringEncoding] attributes:nil] ) )
{
NSLog(#"ERROR WRITING TO FILE: %#\n%#\n%#\n%#", [fileError localizedDescription], [fileError localizedFailureReason], [fileError localizedRecoveryOptions], [fileError localizedRecoverySuggestion]);
}
this has been plaguing me for a while, and this only fails on the device
Try replacing this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, NO);
wit this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
I've replaced NSLibraryDirectory (/Library) with NSCachesDirectory (/Library/Cache). Also denoted to expand tilde to full path which probably is the main cause behind this.

how to access a folder in documents using iphone

i can access .txt file from documents folder but how to access a folder content lets say documents/A
inside A i have ->a.html, update.cfg
now why i cant access update.cfg??
i am getting null value for zipPath
i tried this but no luck
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *aDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"A"];
NSString *zipPath = [[NSBundle mainBundle] pathForResource:#"update" ofType:#"cfg" inDirectory:aDirectory];
still zipPath=NULL??
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *aDirectory = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"A"];
My approach to get to the documentsfolder is a little bit different. (I hope you mean the Documents folder which every application has, not one created by yourself in the mainbundle.^^) I do it like this:
NSString *directoryPath = [[NSHomeDirectory() stringByAppendingPathComponent: #"Documents"] stringByAppendingPathComponent: #"A"];
This is the path to your directory called A in the documents folder. If you know the filename, than you can use another "stringByAppendingPathComponent". ;-) I hope it helps. Else ask again. :-D
after messing up i found this way to acces the file from folder
i got it
NSString *fileName = [NSString stringWithFormat:#"%#/update.cfg",
aDirectory];
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
thanks

Trouble decoding with NSKeyedUnarchiver

I am writing an app targeted at iOS 4.0 on XCode 3.2.3 where I store some data when the app closes using NSCoder protocol. Saving seems to work fine, the problem is retrieving the data from the saved files. My save method looks like this:
-(void)saveMusicalWorksToMemory{
// create the save paths
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *mwPath = [documentsDirectory stringByAppendingPathComponent:kMusicalWorksLocalFileSuffix];
NSString *fwPath = [documentsDirectory stringByAppendingPathComponent:kFeaturedWorksLocalFileSuffix];
NSMutableData *musicalWorksData;
NSMutableData *featuredWorksData;
NSKeyedArchiver *mwEncoder;
NSKeyedArchiver *fwEncoder;
musicalWorksData = [NSMutableData data];
featuredWorksData = [NSMutableData data];
mwEncoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:musicalWorksData];
fwEncoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:featuredWorksData];
// encode the objects
[mwEncoder encodeObject:musicalWorks forKey:kMusicalWorksArchiveKey];
[fwEncoder encodeObject:featuredWorks forKey:kFeaturedWorksArchiveKey];
[mwEncoder finishEncoding];
[fwEncoder finishEncoding];
// write to files
[musicalWorksData writeToFile:mwPath atomically:YES];
[featuredWorksData writeToFile:fwPath atomically:YES];
[mwEncoder release];
[fwEncoder release];
}
And here is the method where I read from the files:
-(void)loadMusicalWorksFromMemory{
// get the path to the locally saved data
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *mwPath = [documentsDirectory stringByAppendingPathComponent:kMusicalWorksLocalFileSuffix];
NSString *fwPath = [documentsDirectory stringByAppendingPathComponent:kFeaturedWorksLocalFileSuffix];
NSFileManager *fileManager = [NSFileManager defaultManager];
if([fileManager fileExistsAtPath:mwPath] && [fileManager fileExistsAtPath:fwPath]){
NSMutableData *mwData;
NSMutableData *fwData;
NSKeyedUnarchiver *mwDecoder;
NSKeyedUnarchiver *fwDecoder;
NSMutableArray *tempMusicalWorks;
NSMutableArray *tempFeaturedWorks;
// unarchive the file data
mwData = [NSData dataWithContentsOfFile:mwPath];
fwData = [NSData dataWithContentsOfFile:fwPath];
mwDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:mwData];
fwDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:fwData];
tempMusicalWorks = [mwDecoder decodeObjectForKey:kMusicalWorksArchiveKey];
tempFeaturedWorks = [fwDecoder decodeObjectForKey:kFeaturedWorksArchiveKey];
[mwDecoder finishDecoding];
[fwDecoder finishDecoding];
[mwDecoder release];
[fwDecoder release];
// restore the content
[self setMusicalWorks:tempMusicalWorks];
[self setFeaturedWorks:tempFeaturedWorks];
}else{
NSLog(#"MusicalWorkManager::loadMusicalWorksFromMemory - No file found at given path");
}
}
The weird thing is that when reading the data from memory and debugging, I see that mwData and fwData are in fact not nil, and have roughly the right size proportions to each other (about 2:1). The problem is though that the decoded arrays (tempMusicalWorks and tempFeaturedWorks) have zero entries (not nil though). This leads me to believe that the problem is actually in the decoding.
For the record, I have also checked that items are being saved in the saveMusicalWorksToMemory() method. The arrays I am passing in through this method are indeed populated with stuff. Also, I have checked that I am implementing the initWithCoder() and encodeWithCoder() methods properly for the objects being encoded and decoded.
Any hints? I'm really lost on this one.
Thanks!
-Matt

Multiple Application Support Directories for iPhone Simulator?

I am developing an iPhone app with someone else. The app works fine for me, but he is running into a bug. We think this bug is related to the fact that he is getting multiple Application directories for this same app. In my ~/Library/Application Support/iPhone Simulator/User/Applications, I only have one folder at all times.
He says that he will get 3 or 4 directories when he is only working on this one app. We think this is our problem because our bug has to do with displaying images that are stored in the app's Documents folder. Does anyone know why he is ending up with multiple directories or how to stop it?
Edit:
Here is the code for writing the image to a file:
NSData *image = [NSData dataWithContentsOfURL:[NSURL URLWithString:[currentArticle articleImage]]];
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *imagePath = [array objectAtIndex:0];
NSFileManager *NSFM = [NSFileManager defaultManager];
BOOL isDir = YES;
if(![NSFM fileExistsAtPath:imagePath isDirectory:&isDir])
if(![NSFM createDirectoryAtPath:imagePath attributes:nil])
NSLog(#"error");
imagePath = [imagePath stringByAppendingFormat:#"/images"];
if(![NSFM fileExistsAtPath:imagePath isDirectory:&isDir])
if(![NSFM createDirectoryAtPath:imagePath attributes:nil])
NSLog(#"error");
imagePath = [imagePath stringByAppendingFormat:#"/%#.jpg", [currentArticle uniqueID]];
[image writeToFile:imagePath atomically:NO];
And here is the code for getting the path when I need the image:
- (NSString *)imagePath
{
NSArray *array = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *imagePath = [array objectAtIndex:0];
return [imagePath stringByAppendingFormat:#"/images/%#.jpg", [self uniqueID]];
}
The app works great for me, but my partner says that the images don't show up intermittently, and he notices that he gets multiple directories in his Applications folder.
I had this problem (I was saving photos in the apps documents directory) and after every new build the directory get's renamed, so my paths were no longer valid. I cooked up these 2 functions (in my app delegate) that will give me a path for the file I want to save or load from the documents or temp directory. Even if the app directory changes, as long as you only store the file name and not the full path, and then use your helper functions to get the path when you need it later you will be ok. Here's my functions for this:
+ (NSString*)fullPathToFile:(NSString*)file {
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:file];
}
+ (NSString*)fullPathToTemporaryFile:(NSString*)file {
return [NSTemporaryDirectory() stringByAppendingPathComponent:file];
}
Works like a charm.