How do I initialize a variable instance which is an object properly? - objective-c

I am an Objective C newbie and I'm sure this is an easy question but I can't figure this out:
I have a class which declares an instance variable called myDeck, which is part of a custom class I created called Deck. Right now I have this in my code:
In the #interface:
Deck *myDeck;
In my init method:
Deck *ourDeck = [[Deck alloc]init];
myDeck = ourDeck;
So this seems to create the myDeck just fine, and I can stick values in it and run it's methods for a while, but I'm running into a spot where it ceases to exist and I get an EXC_BAD_ACCESS error when trying to use it.
I have tried adding
[myDeck retain];
to no avail, it still fails in the same spots. I don't really know how I should be alloc and initting this, I have a feeling I am missing something, anyone?

Everything you're doing there seems right; except I think you might have a typo in your first example - the instance variable is called myDeck, not deck, right? If your object is disappearing it's because you called release or autorelease too many times. Memory management in Cocoa is pretty straightforward. Go check out the documentation for all the information you could ever want.

Related

Confusion with Passing Obj-C objects into methods and retaining the changes to that object

I'm writing a program and trying to learn more about threads, multiprocessing, and such.
My architecture is a Model/View/Controller type.
I have my own subclass of NSImageView (ThumbnailView) and I wanted to be clever and have it listen for a message to clear itself (so all the thumbnails just clear themselves without me having to loop through them).
The problem is my ThumbnailView is controlled by a ThumbnailViewController which is really the one listening for the message. When it gets the message it spins off a new thread with a class object that is the command (ClearThumbnailViewCommand). It passes as an argument a dictionary item containing the associated ThumbnailView object and a key. Within the ClearThumbnailViewCommand I set the image of the ThumbnailView object to be some neutral image (like gray.jpg).
All this works fine, however, the Thumbnail object that changed is not the same Thumbnail object that went in. So I figure I need to pass a pointer rather than the object. I remember something about using MyObject** as opposed to MyObject* and passing via &MyObject but I can't seem to untangle the various combinations. Not being able to reason it out I fell back to my, normally, foolproof system of trying random combinations of things but this time it's not helping.
It seems that even if I'm able to construct a class that passes a pointer (Not sure if I'm using these terms correctly), I'm not able to assign it correctly to the NSDictionary, which doesn't want an id** .
I'll try and include the basics below, if that helps at all.
ThumbnailVew : NSImageView {
ThumbnailVewController * _controller;
}
init {
_controller = [[ControllerClass alloc] initWithControlObject: &self];
}
ThumbnailVewController : ControllerClass {
id ** _controlObject;
}
initWithControlObject: (id**)object {
_controlObject = object;
}
Then when messages are posted a ThumbnailVewController method is called which ultimately does this…
Which, of course will not let me pass in &_controlObject
when it is all re-written so that I can pass _controlObject, I don't get an error, however the ThumbnailView I change is only local to the method.
if([command isEqualToString:#"CLEAR_THUMBNAILS"]) {
NSDictionary * dict;
dict = [[NSDictionary alloc] initWithObjectsAndKeys: &_controlObject, #"thumbnail", nil];
[self newThreadWithCommand:[[[ClearThumbnailViewCommand alloc] initWithArgument:dict] autorelease]];
}
Is this even possible?
Thanks for the feedback. I am indeed just trying to explore some various situations. I understand I may be going a round about way to get at some things but it does help me understand the boundaries more clearly.
In case it might help anyone else, I found a solution to my particular issue. As it turns out I was making the reference to the _controlObject in the init phase of the ThumbnailView. The object created during that phase is different than the ThumbnailView object created when awakeFromNib is called.
when I move the _controlObject assignment to the awakeFromNib method all works as I expected. (Of course I reset the code to not include any of the fancy ** and & declarations.
Again, thank you for helping me understand a bit more about this language. I'm starting to like it quite a bit.

Can't understand what is wrong, get EXC_BAD_ACCESS, any hints?

I'm having this sprite with this in it's init method
lineDrawer = [[LineDrawer alloc]initWithLineColor:ccc3(color.r, color.g, color.b)];
lineDrawer.position = ccp(0,0);
lineDrawer.anchorPoint = ccp(1,1);
[self addChild:lineDrawer];
[self addChild:head];
[lineDrawer release];
Nothing wrong here right? I can release it as addchild is retaining the object.
(autorelease would also be ok)
Although when I have the release I get EXC_BAD_ACCESS(code=1) later on. I've also tried to move the release to the dealloc method but it gives me the same error.
The only object that has reference to lineDrawer is the spriteobject (Player : CCSprite) it's defined in and It doesn't have a getter so it cant even be accessed by another object, so I don't see how this can happen. What can be calling lineDrawer at the time It's dealloced when only the owner has a reference to it?
It happens on the line CC_NODE_DRAW_SETUP() inside the draw method of CCLayer.
Any hints? I know these questions is always hard to solve with the lack of code but It's really hard to know what code to show you. If I knew I could probably solve it by myself. I've also tried to debug this some in instruments but I'm not sure where to look.
Update,
I tried debugging with zombies enabled
Does this say anything to you?
This is the LineDrawer class. It's someone else's class that I've slightly modified.
http://pastebin.com/7Uv4GULy
http://pastebin.com/08NHeVt9
I have a feeling that its some method that's scheduled or something..
Since you add the lineDrawer object to the child collection of your CCSprite, a public reference to it is available through the .children property defined in CCNode.
However, nothing in the code you've posted seems wrong, except that LineDrawer inherits from CCLayer and I don't think that CCLayer was ever designed to be used as a child of a CCSprite ... does it really need to be a child of your Player object? (e.g. should it be following your Player sprite as it moves and rotates?) Typically a layer is a child of your active CCScene node, or another layer.
Most of these problems don't happen anymore when you are using ARC.
Most likely you have over-released an object. It doesn't necessarily need to be the lineDrawer. Perhaps it's an object inside the lineDrawer class.
Best way to figure this out is to enable NSZombieObjects in the build scheme and find out which object was accessed.

How to implement CHCircularBuffer in iOS project?

for my game iOS project I need a ring buffer. It should work similar to a queue where elements go out and go in but the total amount of elements in the buffer should stay the same.
I implemented the ring buffer successfully using java but I am not so familar with objective-c. I found a ring buffer implementation on the web called CHCircularBuffer: https://bitbucket.org/devartum/chdatastructures/src/4d6d7194ee94/source/CHCircularBuffer.m However I failed implementing it correctly.
The circular buffer is a property of a class called TerrainManager which does all the mathematical terrain generation.
#interface TerrainManager : NSObject{
int terrainParts;
CHCircularBuffer* circularTerrainBuffer;
}
#property(nonatomic, retain) CHCircularBuffer *circularTerrainBuffer;
#end
This how the ring buffer is initialized in the implementation of TerrainManager
circularTerrainBuffer = [[CHCircularBuffer alloc] initWithCapacity:parts];
This creates an instance of the buffer and sets the size property to parts. Now I add objects to the buffer using addObject method:
[circularTerrainBuffer addObject:[NSNumber numberWithDouble:0.2]];
Sometimes this line receives an error "exec_bad_access". E.g. when I init the buffer with capacity of 15 everything is fine, with 20 I get the error.
I now try to access the buffer from the terrain class where the drawing takes place. But whenever I try to access the objects I get an "bad_access" error.
NSArray *arr = [terrainManager.circularTerrainBuffer allObjects];
E.g. this line would create the error.
So there is something wrong with my code. Maybe I dont understand the buffer and add objects the wrong way. I dont know. Any ideas or suggestions?
The snippets of code you are showing are correct. I implemented a small project to test CHCircularBuffer the way you specify and it works correctly. So, the problem must be somewhere else.
The only way around this is, IMHO, put a breakpoint on the line that fails and step into the addObject function to see where exactly it fails. The array could be reallocated in there, so may be this is failing and giving the bad access. The same for allObjects.
Anyway, I have to say that I could execute my test without any issue, adding objects, removing them from head and tail, and getting the array of all objects with no issues.
If you post more code, we can maybe help a bit more.

Small Memory Issue with Objective-C

I made a Mac OS X app that basically runs an NSTask. The thing is, I made a class called XXTask to handle a file, and a class called XXController to handle the drag and drops in the GUI and asking the XXTask to handle a file now and then.
I had made almost the same thing in the past, and it worked fine. This time, I added a delegate protocol, and made XXController the delegate of XXTask.
When XXTask fails, I ask the delegate to show a particular view, and thus call a method like this :
[delegate showView];
This works, but when trying to relaunch using the information I stored on the first launch, the app outputs errors. I used NSLog to see what exactly was wrong, and it seems like three instance variables (two NSStrings and one NSMutableArray) are (null).
These are the three instance variables :
NSString *curFilePath;
NSArray *lastArgs;
NSString *lastLaunchPath;
I create them like this :
curFilePath = filename;
// filename is an NSString passed to the method where I first create curFilePath
// the object passed to the method is a retained NSString (an instance variable of XXController)
lastArgs = [[NSMutableArray arrayWithObjects:curFilePath, [curFilePath stringByDeletingLastPathComponent], nil] retain];
lastLaunchPath = [[[NSBundle mainBundle] pathForResource:#"xxtask" ofType:#""] retain];
All three variables are null, but the XXTask object is not, as it can still execute code.
Errors :
2011-01-15 16:38:57.233 App[24179:a0f] PATH : (null)
2011-01-15 16:40:52.846 App[24212:a0f] LAST ARGS : (null)
2011-01-15 16:40:52.847 App[24212:a0f] LAST LP : (null)
2011-01-15 16:40:52.847 App[24212:a0f] Exception detected while handling key input.
2011-01-15 16:40:52.848 App[24212:a0f] *** -[NSCFArray insertObject:atIndex:]: index (1) beyond bounds (1)
When I don't draw the view by calling the delegate, everything is okay. I could put that view method in the XXTask class, but I'd rather find a neat explanation to this first. What happens when I call the delegate? (It's the first time I tried using delegate protocols)
Thanks for answering!
If this code looks horrible to you, I have two excuses :
I've been messing around for a long
time, read the memory management
docs and did the most silly things.
Reference-count memory management is quite new to me. I've
never made real big apps like this
one in the past, so I normally can't
do a lot wrong, but this time memory
is way more important.
If I understand this correct (it's pretty hard without any code) you store some information held in XXTask, right?
Do you retain/copy the data? If not, it gets released as soon the XXTask gets released.
If I misunderstand your question, I ask you to provide some code which demonstrates your problem. This makes finding errors much easier.

How to pass message to instance from a different class in objective c?

Stuck on what I figure is simple thing here. Basically I need to pass a pointer to an object as an argument into an instance method of another class. Said differently: I have a class that creates "Things" and I have an instance of another class that I want to receive the "Things."
Working with Cocos2D frameworks. The Things are a custom subclass of CCSprite, and the instance that receives them is a CCLayer.
I figure I'm misunderstanding something basic about ivars or maybe properties here. Any pointers in the right direction would be appreciated.
Here's the interface for ThingLayer, which should receive the "thing":
#interface ThingLayer: CCLayer {
CCTextureAtlas *textureAtlas;
ThingLayer *thingLayer;
NSMutableArray *ThingsArray;
}
- moveThingtoLayer:(Thing*)athing;
#end
And here's how I'm trying to message to the instance, from outside the class:
[ThingLayer moveThingtoLayer:thing];
I realize I'm asking the class here, not the instance... which is giving me "may not respond to..." errors. But this isn't working either (asking name of instance)...
[thingLayer moveThingtoLayer:thing];
Any obvious answers?
Looks like you should have
ThingLayer *thingLayer = [[ThingLayer alloc] init];
[thingLayer moveThingtoLayer: thing];
As a side thought, you most likely want to init a new thing in thingLayer so that instance owns the Thing, and release thing after calling moveThingToLayer.