EXC_BAD_ACCESS - iPhone - iphone

My iPhone app is crashing and getting EXC_BAD_ACCESS error when using this code:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"stats.plist"]; //3
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) //4
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"stats" ofType:#"plist"]; //5
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
[bundle release];
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//load from savedStock example int value
score.highScore = [[savedStock objectForKey:#"score"] intValue];
score.deaths = [[savedStock objectForKey:#"deaths"] intValue];
score.iFallPoints = [[savedStock objectForKey:#"iFallPoints"] intValue];
score.difficulty = [[savedStock objectForKey:#"difficulty"] intValue];
[savedStock release];
score is the singleton I am accessing.

You didn't alloc or retain bundle; don't release it.
See the memory management programming guide if you need help understanding it.
Also, the static analyzer can be helpful for pointing some out memory bugs.

Related

Cannot read/write from/to plist on device, but can in simulator

i've been looking at a lot of posts with a similar problem here on Stackoverflow, but i still cannot figure out why i can't write/read my plist.
Here is my method to load my plist into the app.
This should copy the plist to the device's documents folder and not resources folder, correct?
-(void)loadPlist:(NSString*)plistString {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.plist", plistString]];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path]) {
NSString *bundle = [[NSBundle mainBundle]pathForResource:plistString ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
} else {
NSLog(#"%# already exists",path);
}
}
This is how i write to my plist:
-(void)writeScore:(NSString*)objectstring forPlayer:(int)playerTag {
switch (playerTag) {
case 1:
NSLog(#"Wrote to 1");
holeInt = [P1hole_Label.text integerValue];
plistpath = [[NSBundle mainBundle]pathForResource:#"Scores" ofType:#"plist"];
plistdata = [[NSMutableDictionary alloc]initWithContentsOfFile:plistpath];
[plistdata setObject:[NSString stringWithString:objectstring] forKey:[NSString stringWithFormat:#"Hole %i", holeInt]];
[plistdata writeToFile:plistpath atomically:YES];
break;
Etc.
And here is how i read the plist:
-(void)createNewHoleLabel:(NSString*)plistString andSetX:(int)x {
//SetX; 0 = P1, 1 = P2 etc.
UILabel *label = [UILabel new];
[label setFrame:CGRectMake(80 + 53 * x, 93 + 26 * integer, 50, 25)];
NSString *path = [[NSBundle mainBundle]pathForResource:plistString ofType:#"plist"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]initWithContentsOfFile:path];
label.text = [dict objectForKey:[NSString stringWithFormat:#"Hole %i", integer + 1]];
[label setAdjustsFontSizeToFitWidth:YES];
[label setTextAlignment:NSTextAlignmentCenter];
integer++;
[scrollview addSubview:label];
}
I hope you can help me. Please ask for further details if needed.
In writeScore:forPlayer:
plistpath = [[NSBundle mainBundle]pathForResource:#"Scores" ofType:#"plist"];
...
[plistdata writeToFile:plistpath atomically:YES];
You are trying to write to the the App's bundle which can not be done on the device. You should be writing the the Documents directory.

Increment Number in plist

I am using the method below to get an array from my plist and then increase a certain value by 1, then save it. However I log the array and the value doesn't actually go up each time.
In my plist, I have an array and in that number values, each one is set to 0. So every time I run this again it goes back to 0 it seems.
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"Words.plist"];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:finalPath];
NSMutableArray *errors = [dict objectForKey:[NSString stringWithFormat:#"Errors%d.%d", [[stageSelectionTable indexPathForSelectedRow] section] +1, [[stageSelectionTable indexPathForSelectedRow] row] +1]];
int a = [[errors objectAtIndex:wordIndexPath] intValue];
a += 1;
NSNumber *b = [NSNumber numberWithInt:a];
[errors replaceObjectAtIndex:wordIndexPath withObject:b];
[errors writeToFile:finalPath atomically:YES];
You can only write to a file in the documents-folder. You can't write to your bundle!
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Namelist.plist"];
You can use NSFilemanager to copy your Plist-File to the documents-folder.
To get the path of your file:
- (NSString *)filePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"MyFile.plist"];
return filePath;
}
To copy the file if it doesn't exist:
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:[self filePath]]) {
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyFile" ofType:#"plist"];
[fileManager copyItemAtPath:path toPath:[self filePath] error:nil];
}
Now you can write your NSDictionary to the Documents-Directory:
[dict writeToFile:[self filePath] atomically:YES];
But you really need to update the array in the dict!
You are writing the array to disk, instead of the dictionary that the array originated from:
[dict writeToFile:finalPath atomically:YES];
Also, you will need to replace the Errors%d.%d object with the updated one before saving it:
[dict setObject:errors forKey:/* your formatted key*/];
Finally, as #mavrick3 pointed out, you cannot save files to your bundle, only to your application's documents directory.

Sharing multiple files on App Via iTunes File Sharing (Code shows 1 file)

I'm trying to file share multiple files with iTunes file share.
Here is the current code.
Delegate.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
// file sharing trying
{
NSString *fileName = #"Test.mp3";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:fileName];
if (![fileManager fileExistsAtPath:documentDBFolderPath])
{
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
}
[self.window makeKeyAndVisible];
return YES;
}
At the moment only 1 file gets shared.
Thanks
I assume you want to add a bunch of files in an NSArray? then loop through it like this:
NSArray *names = [NSArray arrayWithObjects: #"foo", #"bar", nil];
for (NSString *fileName in names)
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *documentDBFolderPath = [documentsDirectory stringByAppendingPathComponent:fileName];
if (![fileManager fileExistsAtPath:documentDBFolderPath])
{
NSString *resourceDBFolderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
[fileManager copyItemAtPath:resourceDBFolderPath toPath:documentDBFolderPath error:&error];
}
}

Terminating app due to uncaught exception 'NSInvalidArgumentException'

I've finished my own project.
So I tested it on the simulator and everything is ok.
But unfortunately, the project does not run on my real iphone. This error occurs:
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSFileManager copyItemAtPath:toPath:error:]: source path is nil'"
What is the reason?
Here is some code that I used:
RootViewController *rootViewController;
...
- (void) startApp;
{
[rootViewController init]; // error occured
}
RootViewController is one of Project Simple File.
void Game::readData()
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"GameInfo.plist"]; //3
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) //4
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"GameInfo" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//load from savedStock example int value
gameMaxLevel = [[savedStock objectForKey:#"GameMaxLevel"] intValue];
[savedStock release];
}
void Game::readData()
{
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
NSString *documentsDirectory = [paths objectAtIndex:0]; //2
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"GameInfo.plist"]; //3
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path]) //4
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"GameInfo" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//load from savedStock example int value
gameMaxLevel = [[savedStock objectForKey:#"GameMaxLevel"] intValue];
[savedStock release];
}
check if your GameInfo.plist exist in your application's resource, and it reside inside your application folder(if you are executing your code on two or more devices). If problem doesn't get solved, share your, complete exception log.

how to save data in plist in iphone through iphone app [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to write data in plist?
hi i am now in iphone programming. i want ti add data and save it in plist ....-
i am using following code...
(void)viewDidLoad {
[super viewDidLoad];
NSLog(#"i amin did load");
temp =[self readPlist:data];
NSLog(#"dict data is %#",temp);
[self writeToPlist];
temp =[self readPlist:data];
NSLog(#"dict data is %#",temp);
}
//
// NSError *error;
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); //1
// NSString *documentsDirectory = [paths objectAtIndex:0]; //2
// NSString *path = [documentsDirectory stringByAppendingPathComponent:#"data.plist"]; //3
//
// NSFileManager *fileManager = [NSFileManager defaultManager];
//
// if (![fileManager fileExistsAtPath: path]) //4
// {
// NSString *bundle = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"]; //5
//
// [fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
// }
// NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
//
// NSLog(#"dictionary value is %#",savedStock);
//
// value = [[savedStock objectForKey:#"india"] intValue];
// NSLog(#"value in plist is %d",value);
// [savedStock release];
- (NSDictionary *)readPlist:(NSString *)fileName
{ NSLog(#"i am in readlist method");
NSLog(#"file paased is %#",fileName);
//NSData *plistData;
// NSString *error;
// NSPropertyListFormat format;
// NSDictionary *plist;
NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"plist"];
NSMutableDictionary *plistDict=[[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
return plistDict;
}
- (void)writeToPlist
{
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
[plistDict setValue:#"karachi" forKey:#"pakistan"];
[plistDict setObject:#"lahore" forKey:#"amerika"];
[plistDict setObject:#"jabalpur" forKey:#"mp"];
[plistDict writeToFile:filePath atomically: YES];
/* This would change the firmware version in the plist to 1.1.1 by initing the NSDictionary with the plist, then changing the value of the string in the key "ProductVersion" to what you specified */
}
When you call writeToFile:atomically you don't need to give the full path, just the file name. It will automatically put it in the documents directory.
Basically, everywhere where you have written the variable filePath just write #"whatever.plist".