views:

85

answers:

4

Sorry about the title being extremely vague, I'm new to Objective C and struggling a little with it. Basically I have the following section of code:

Graph *graph1 = [[Graph alloc] init];
[graph1 addNode:@"TEST"];

which is working to a degree. But I want to change it because the above code happens on a button press, and therefore I assume I am creating a new "*graph1" every time I do this. I thought I could simply change it to this:

if(self = [super init]) 
{
    [self setGraph: [[Graph alloc] init]];
}
return self;

Where the above is in the init method, and below is the modified function:

[graph addNode:@"TEST"];

However when debugging I've found addNode method is never called when it's like this.

Thanks Zac

This is testViewController.h

#import <UIKit/UIKit.h>
@class Graph;
@class Node;

@interface testViewController : UIViewController {

    Graph       *graph;
    UILabel     *label;

}


@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, retain) Graph *graph;

- (IBAction) buttonPressed:(id)sender;

@end

This is textViewController.m

#import "testViewController.h"
#import "Graph.h"
@implementation testViewController

@synthesize  label, graph;

- (id)init
{
    if(self = [super init]) 
    {
        [self setGraph: [[Graph alloc] init]];
    }
    return self;
}

- (IBAction)buttonPressed:(id)sender
{
    //Graph *graph1 = [[Graph alloc] init];
    [graph addNode:@"TEST"];


    Node *node1 = [[Node alloc] initWithLabel: @"LABEL"];
    label.text = node1.label;
}
A: 

Have you declared the graph variable in the header? ie: Graph *graph; and the corresponding @property (nonatomic, retain) Graph *graph;

Then I would do this:

   -(id) init {
        graph = [[Graph alloc] init];
        [graph retain];
    }

that might help (the only reason I think it wouldn't would be because a) if your variable wasn't declared then you would get a warning like graph may not respond to addNode and if it wasn't retained then your app would crash when it runs)... other than that, I can't see what would be the problem. If that doesn't work, can you please post all your code from your .h and .m files?

Thomas Clayson
A: 

Then I would do this:

-(id) init {
        graph = [[Graph alloc] init];
        [graph retain];
    }

that might help

This would result in a memory leak. The retain count of the object pointed to by graph will have a retain count of 2. Not ideal. If you declare the property with the retain attribute then

[self setGraph:[[[Graph alloc] init] autorelease]];

should do it. I go with -

self.graph = [[[Graph alloc] init] autorelease];

There could be many reasons the addNode: method is not being called. Put break points in the enclosing method and see if everything is working as you expect it to.

Sreejit
it wouldn't result in a memory leak if you release it properly... if there is a retain property then there's no guarantee that by the time you come to call the variable that it is still in memory. after a certain amount of lines of code a variable can be forgotten in objective c. This will result in an error when you try to access the variable. This can be sorted by adding a retain to the variable. Plus, I suggested that this may be, but probably wasn't, the problem.
Thomas Clayson
+1  A: 

The first thing that comes to mind is that graph is nil and thus invoking a method (sending a message) to it will result in nothing. An unwanted release will cause an EXC_BAD_ACCESS, and this seems to be not the case.

I suppose you are calling all of this in a UIViewController subclass, right? Are you sure the right init is called? If you are using a NIB you should override the -(id)initWithNibName:bundle: and place you code there. I guess the code is probably in the plain -(id)init, since you are calling [super init] and not [super initWithNibName:nameOrNil bundle:bundleOrNil], but this way, if initialize the controller with the NIB you custom code is never called and thus graph is nil.

By the way, if the graph property is (retain) you are also causing a memory leak in the init.

sigsegv
Yeah I'm calling it in the -(id)init method. I'll try using -(id)initWithNibName:bundle:
Zachary Markham
Okay I'm going to have to be a complete noob and ask where I find my nib name?
Zachary Markham
The file with the xib extension. Probably it's @"testViewController"
Lou Franco
You shouldn't need to call initWithNibName:bundle -- @sigsegv is suggesting that that is the init method you need to override. It's already being called for you and your init is not being called.
Lou Franco
It is usually in the resources folder and has the same name of your UIViewController class, but with a .xib (yeah, .xib) estension, but the UIViewController doesn't not care for the name of the nib at all. You just need to have a -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundle method defined and call the super implementation in its body. If you are using one of the sdk "template" application it is probably missing from the source, but if you add a new UIViewController class to the project you'll find it commented. A quick look at it will make a lot of things clear.
sigsegv
Hey thanks for all the help, I had a good look around at the initWithNibName stuff and thought I had it working but then it just didn't again. However! I've fixed it! I simply moved the self.graph = [[[Graph allo] init] autorelease]; into a -(void)viewDidLoad method. I can't believe all that testing and modifying and retrying was all fixed with 3 lines of code! Thanks for all your help sigsegv :)
Zachary Markham
A: 

I'm sure you're through this problem now, but I agree that the reason "add" is "not being called" is that your graph object is nil at that moment

I'd say, first put a test message around your "addNode" call

 NSLog(@"We tried to add here");
[graph addNode:@"TEST"];

That will show you that the add is being called -- I bet it is.

Then, where you had your previous call to initialize "graph" right before your add call, try conditionally initializing it:

 if(graph == nil) graph = [[Graph alloc] init];
[graph addNode:@"TEST"];

Note, this is all just to find the problem. Finally I'd say you have some challenges in here with how you are dealing with memory. You may not have reference issues, but later leaks. And depending upon how often this code is executed it could be an issue.

But at least you may get to your issue easier with the above tests.

bladnman