Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
Ok, so here's an interesting problem with a Cocoa application I'm building.

The basis of this application is an NSMutableArray. When I close the program, it uses this code to save the array;

Code:
	NSString *path = [self pathForDataFile]; 
	
	NSMutableDictionary *rootObject; 
	rootObject = [NSMutableDictionary dictionary]; 
	
	[rootObject setValue: partsList forKey:@"partsList"]; 
	[NSKeyedArchiver archiveRootObject: rootObject toFile: path];

Then, when the program starts, it uses the following code to load the array(after initializing it of course);

Code:
	NSString *path = [self pathForDataFile]; 
	NSDictionary *rootObject; 
	
	rootObject = [NSKeyedUnarchiver unarchiveObjectWithFile:path]; 
	setPartsList: [rootObject valueForKey:@"partsList"];

Now, when I run the program once, it works fine. When I close it, it creates the data file. However, when I run the program a second time to load the saved information, I get a EXC_BAD_ACCESS error sometime after it loads the array. Could this have something to do with access permissions for the file in question?

PS. I looked up this error message, and everything I find on google points to memory management issues dealing with retaining and releasing objects. My understanding is that since my project is set to use Garbage Collector, I don't have to worry about retain, release and autorelease commands, is that correct?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
When you get that error, is the debugger available? If so, what's the stack trace look like?

Is the last line of the code you posted correct? I would guess that doesn't compile.
 

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
I'm not sure what you mean by stack trace. The debugger is available though.

I've actually changed my code. It doesn't give me the error anymore, but it either doesn't save the array, or doesn't load the array. I'm not sure which.

The saving code is now;

Code:
	NSString *path = [self pathForDataFile]; 
	[NSKeyedArchiver archiveRootObject: partsList toFile: path];

While the loading code is now;

Code:
	NSString *path = [self pathForDataFile]; 
	setPartsList:[NSKeyedUnarchiver unarchiveObjectWithFile:path];

I didn't see any reason to use the NSMutableDictionary, so I replaced it with the setter and getters for the partsList array, which is the array that I want to save. Like I said, I'm not getting the error anymore, but when I close and re-open the application, it's starting with a blank array instead of the saved version.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
heh, ok I understand the problem now.

Code:
setPartsList:[NSKeyedUnarchiver unarchiveObjectWithFile:path];

This isn't doing what you think it's doing. Let me rewrite it:

Code:
setPartsList:
    [NSKeyedUnarchiver unarchiveObjectWithFile:path];

Instead of assigning partsList to the unarchived object, you're defining a label for use with the C goto statement, and then ignoring the result of unarchiveObjectWithFile.

Try this instead:

Code:
partsList = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

Or if you have setPartsList: defined as a method you can use that too:

Code:
[self setPartsList:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];
 

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
Thanks dude, I used your second example and it works perfectly now.

Question though. In some applications, I've been able to call a method within the same class without calling it as [self method]. Is there some rule as to when I need to call "self" and when I don't?
 

Daphtdazz

macrumors member
Nov 10, 2007
48
0
Oxford
Hey,

Objective-C is essentially just an extension to C (with a modified run-time and all that behind the scene). Thus, if you write a bit of code that would mean a certain thing in C, that is what it will mean in Objective-C.

So if you write what you wrote above, that would be defining a label for the goto command, as said.

The only way that you can send an objective-C message is by using the

[target method]

syntax.

So if you have an instance variable and you want to access it within your class's implementation, you could access it directly, or by calling its getter method, which will often have the same name as the variable. Thus you have two things which look the same, and get the same result, but are completely different in implementation.

So, if I have a class:

@interface AClass : NSObject {
id someObject;​
}

-(void)aMethod;
-(id)someObject;

@end

@implementation AClass
-(void)aMethod{
[someOtherObject doSomethingWith:someObject];​
// Or:
[someOtherObject doSomethingWith:[self someObject]];​
}
-(id)someObject{
return someObject;​
}
@end

In the first version, someObject is the actual object, and in the second someObject is a selector that you pass to AClass to get the instance variable.

Hope this helps.
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
Do C programmers ever actually use goto? Last time I used anything like that was with Commodore BASIC. It almost seems like bad form, I personally would not object to having labels and goto simply go to the dustbin of history.
 

Cinder6

macrumors 6502a
Jul 9, 2009
509
50
Not usually, no, but it's there. I've seen a couple examples where goto is more elegant than other methods, but they were just proof-of-concepts.
 

jpyc7

macrumors 6502
Mar 8, 2009
276
0
Denver, CO
Do C programmers ever actually use goto? Last time I used anything like that was with Commodore BASIC. It almost seems like bad form, I personally would not object to having labels and goto simply go to the dustbin of history.

I see goto in network driver code to deal with errors. This is because nearly all drivers are written in C (not C++ where there is support for exceptions) which is because a lot of unix-like OSes (FreeBSD, Linux) are written in C.

BadWolf13 said:
Question though. In some applications, I've been able to call a method within the same class without calling it as [self method]. Is there some rule as to when I need to call "self" and when I don't?

I'm weak on Obj-C, but I think it has to do with whether it is a class method or not. That is the terminology used in C++ when a method belongs to the class and not a single instance. You don't need the self for class methods.
 

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
Thanks Daphtdazz, that does help explain it.

My last question on this topic. In the future, I'm going to rewrite the save and load methods to save and load three separate arrays. As I'll be using NSKeyedArchiver and NSKeyedUnarchiver, does it matter what order I put the archiving and unarchiving commands, or will they always find the right data because they're keyed?
 

HiRez

macrumors 603
Jan 6, 2004
6,250
2,576
Western US
As I'll be using NSKeyedArchiver and NSKeyedUnarchiver, does it matter what order I put the archiving and unarchiving commands, or will they always find the right data because they're keyed?

It doesn't matter, but you probably want to error-check for the existence of each key first, and have a default value ready in case it doesn't exist, or throw an exception/alert.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Do C programmers ever actually use goto? Last time I used anything like that was with Commodore BASIC. It almost seems like bad form, I personally would not object to having labels and goto simply go to the dustbin of history.

Apple uses it a lot, just look through some of their kernel code. It's nice when using lots of Core Foundation objects to give your function a clean structure and separate all the release/frees from the actual logic.
 

Daphtdazz

macrumors member
Nov 10, 2007
48
0
Oxford
I suppose it's like a lot of things in coding. If used responsibly and with a particular design and methodology in mind, goto commands are very powerful and can greatly clarify code.

However, new programmers are told that they must never use them, which generally will be good advice because you don't achieve great code design and methodology over night... the potential for bollocksing it all up is large.
 

Krevnik

macrumors 601
Sep 8, 2003
4,100
1,309
Apple uses it a lot, just look through some of their kernel code. It's nice when using lots of Core Foundation objects to give your function a clean structure and separate all the release/frees from the actual logic.

That's usually where I see it a lot as well. It helps when someone comes after you trying to maintain the code, as they can see where cleanup is done, and don't have to have quite as intimate a knowledge of the function in order to modify it to do something new or fix a bug.
 

gnasher729

Suspended
Nov 25, 2005
17,980
5,565
Is the code that you posted exactly what you are running? In that case, turn on all the compiler warnings. And figure out why you get a warning for an "unused label". And probably a warning that setPartsList is used without being defined.

Question though. In some applications, I've been able to call a method within the same class without calling it as [self method]. Is there some rule as to when I need to call "self" and when I don't?

You always send a method to some object. Object methods are often sent to self, or to some other object. Class methods are sent to a class. But there is always _some_ receiver for the message.
 

Jimmetry

macrumors member
Feb 11, 2009
56
0
I know this is an oldish thread but EXC_BAD_ACCESS is almost always caused by bad memory management. I happened to find this thread by naively running into the same issue.

If you don't alloc it, you can't keep it unless you retain it.

partsList = [[NSKeyedUnarchiver unarchiveObjectWithFile: path] retain];

Otherwise it'll be alive until the function returns but no guarantees past that point.
 

Sydde

macrumors 68030
Aug 17, 2009
2,552
7,050
IOKWARDI
I know this is an oldish thread but EXC_BAD_ACCESS is almost always caused by bad memory management. I happened to find this thread by naively running into the same issue.

If you don't alloc it, you can't keep it unless you retain it.

partsList = [[NSKeyedUnarchiver unarchiveObjectWithFile: path] retain];

Otherwise it'll be alive until the function returns but no guarantees past that point.

Even then, if you are using an autorelease pool (e.g., threading) that should be drained periodically within a long loop, you need to make sure not to lose things (like enumerators or scanners) when you between pools.
 

BadWolf13

macrumors 6502
Original poster
Dec 17, 2009
271
0
Just to double check something. My understanding from Aaron Hillegass' book is that if you're using Garbage Collector, you don't need to bother with retain, release or autorelease. Is that right?
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Just to double check something. My understanding from Aaron Hillegass' book is that if you're using Garbage Collector, you don't need to bother with retain, release or autorelease. Is that right?

yes, that's right. You can still do them to your hearts content, but they won't have any affect.

-Lee
 

Jimmetry

macrumors member
Feb 11, 2009
56
0
Just to double check something. My understanding from Aaron Hillegass' book is that if you're using Garbage Collector, you don't need to bother with retain, release or autorelease. Is that right?

Was the "PS" part of your original post always there? Somehow I missed it. Well yes, the garbage collector will indeed handle all that for you.

In that case, you should be checking to make sure the object was created. A bit of error handling will stop EXC_BAD_ACCESS (and instead you can show a dialog), and if NSKeyedUnarchiver gives detailed exception reasons, it might also tell you why the problem is occurring in the first place.
 

Jimmetry

macrumors member
Feb 11, 2009
56
0
Do C programmers ever actually use goto? Last time I used anything like that was with Commodore BASIC. It almost seems like bad form, I personally would not object to having labels and goto simply go to the dustbin of history.

There are a few circumstances where it can be useful (which is probably why it still exists) but it's not popular. The only accepted goto-esque feature is the switch statement.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.