1

I have initialised a custom class from within another class, I then want to run a function from the custom class and when it's done call a method from the class which initialised it.

// classA.m

-(void)methodA {
    // do some complicated stuff
    if (result) {
        [classB methodB];
    }
}

// classB.m    

-(void)methodA {
    classAInstance = [[classA alloc] init];
    [classAInstance methodA];
}

-(void)methodB {
    // got result, do more stuff
}

[classB methodB] doesn't work, but I have no clue how this would be achieved so any help would be greatly appreciated, thanks.

Nat Ritmeyer
  • 5,634
  • 8
  • 45
  • 58
amba88
  • 759
  • 3
  • 9
  • 27
  • The way you have it written it won't work. You would need to change the little '-' in classB:methodB to a '+' for a class method. – JiuJitsuCoder Jul 06 '13 at 13:18

4 Answers4

2

I'm new to objective-c so please bear with me.

I'll keep my clothes on for this one--if you don't mind.

One way to achieve what you want is through 'composition', which means write A so that it has a member variable that is an instance of B. Then A can use that instance of B to call methods in B:

A.h:

#import <Cocoa/Cocoa.h>
#import "B.h"

@interface A : NSObject {
    B* my_b;
}
- (id)init:(B*)b;
- (void)methodA;

@end

.

A.m:

#import "A.h"

@implementation A

- (id)init:(B*)b
{
    if (![super init])
    {
        return nil;
    }

    my_b = b;

    return self;
}

- (void)methodA 
{
    [my_b methodB];
}

@end

.
B.h:

#import <Cocoa/Cocoa.h>

@interface B : NSObject {

}
- (void)do_stuff;
- (void)methodB;

@end

.
B.m:

#import "B.h"
#import "A.h"

@implementation B

- (void)do_stuff
{
    A* a = [[A alloc] init:self];
    [a methodA];
}

- (void)methodB
{
    NSLog(@"hello");
}

@end

===

Because you wrote:

[classB methodB];

...maybe you want to call a class method in B.

A.h:

#import <Cocoa/Cocoa.h>
#import "B.h"

@interface A : NSObject {

}
- (void)methodA;

@end

A.m:

#import "A.h"
#import "B.h"

@implementation A

- (void)methodA 
{
    [B classMethodB];
}

@end

B.h:

#import <Cocoa/Cocoa.h>

@interface B : NSObject {

}
+ (void)classMethodB;
- (void)do_stuff;

@end

B.m:

#import "B.h"
#import "A.h"

@implementation B

- (void)do_stuff
{
    A* a = [[A alloc] init];
    [a methodA];
}


+ (void)classMethodB   //Note the '+'
{
    NSLog(@"hello");
}

@end
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
7stud
  • 46,922
  • 14
  • 101
  • 127
  • I tried this but I get an error on the line `[my_b methodB];` saying `"Receiver type 'B' for instance message is a forward declaration'`. – amba88 Jul 06 '13 at 02:14
  • You are missing in import somewhere. – 7stud Jul 06 '13 at 02:30
  • If I import B.h in A.h I get the error `ld: 1 duplicate symbol for architecture armv7 clang: error: linker command failed with exit code 1 (use -v to see invocation)` – amba88 Jul 06 '13 at 02:33
  • Why don't you just look at my imports and copy them? The files with `@interface` in them are .h files; the files with `@implementation` in them are .m files. Adding the other files to my post.. – 7stud Jul 06 '13 at 02:37
  • 7stud, maybe I'm not fully grasping this, but wouldn't your 'B' class call an entirely different 'A' method? This wouldn't link to the original 'A' object that created the child 'B' object. – JiuJitsuCoder Jul 06 '13 at 02:55
  • @MySpecialPurpose, As far as I can tell, my code follows the same pattern used by the op: In the op's code, nothing in A creates a B object. Instead, a method in B creates an A instance, and the A instance is used to call a method in A. Then the op wants to know how the method in A can be made to call a method in B. However, after rereading the op's code, maybe the op wants to call a class method in B? I'll add some code for that. I don't see anything related to inheritance in the code, but now I see the term 'parent' in the title of the post. – 7stud Jul 06 '13 at 05:24
  • 7stud, I see what you mean. What the OP writes in code and what he says in text seem to be two different things. I made a comment on the OP as well about switching to a class method since that would at least make the code work. It still seems weird to me...like there is an extra retain of a Class A object that won't get dealloc'd. Either way I +1'd your answer because you covered all the possibilities. – JiuJitsuCoder Jul 06 '13 at 13:22
  • @MySpecialPurpose, I assume that when someone says they are a beginner, memory management isn't necessarily something they are dealing with yet. – 7stud Jul 06 '13 at 13:48
1

I think there is something very crucial that is being overlooked here by the other posters: retain cycles. Any child method that is trying to reference its parent object needs to do so with a weak reference or an __unsafe_unretained modifier. If you don't you run the risk of having the parent object caught in a retain cycle. If I understand the question, you simply want to call a method in a class 'A' object when a certain method finishes in a class 'B' object? I usually do this one of two ways: delegates and protocols (the more difficult concept) or NSNotificationCenter (the less difficult concept). In your case, since you are just trying to 'notify' one method when another method in a different class completes, the notification center seems like it would be far easier to use. There is a pretty good tutorial here: http://blog.isotoma.com/2009/11/on-objective-c-delegates-and-nsnotification-objects/ but here is the basic premise:

In the method doing the work (in Class B) at the end of the method you insert something like this:

NSNotification* notification = [NSNotification notificationWithName:@"MyNotification" object:self];  
[[NSNotificationCenter defaultCenter] postNotification:notification];

Then, in the class A init method you would register to receive that notification:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(MethodToCallAfterNotification:) name:@"MyNotification" object:nil];

Whenever the class B method finishes, it will broadcast a 'MyNotification' notification. Your class A object is listening for those notifications, so it will automatically call whichever selector you designate whenever that notification is broadcast in your app.

Just be sure to create a dealloc method in your class A implementation file and unregister the observer like this:

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];

If you are interested in learning how to do this with a weak referenced delegate method call, I posted an answer about that here: https://stackoverflow.com/a/10273551/1318525

Community
  • 1
  • 1
JiuJitsuCoder
  • 1,866
  • 14
  • 13
0
#classA.m

-(void)methodA:(classB *)classB {

#classB.m    

[classAInstance methodA:self];
Danilo
  • 3,257
  • 2
  • 19
  • 24
0

Before calling the method you have to initialize a object of the class to call a explicit method ... like as

// classA.m
- (void)somethingA{ }

Your code will work if the method is implicit method of the class, where you don't need to create or initialize classes object, but remember that implicit method can only called by the class.. like as

// classB.m
+ (void)somthingB {}
NULL
  • 1,848
  • 1
  • 21
  • 23