Call method from parent class - objective-c

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.

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

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

#classA.m
-(void)methodA:(classB *)classB {
#classB.m
[classAInstance methodA:self];

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 {}

Related

calling Objective-C super class implementation without overridden methods

it seem like when messaging a super class from a subclass that has overridden some methods, you can't get the "original" implementation by just using super. any work arounds or should i init that super class?
here some code showing what i mean:
#interface ClassA : NSObject
- (void)method1;
#end
#implementation ClassA
- (void)method1
{
[self method2];
}
- (void)method2
{
NSLog(#"Hello it's ClassA");
}
#end
#interface ClassB : ClassA
- (void)method3;
#end
#implementation ClassB
- (void)method2 // overriding method2
{
NSLog(#"Hello it's ClassB");
}
- (void)method3
{
[self method1]; // logs "Hello it's Class B" as expected
[super method1]; // still logs "Hello it's ClassB" instead of "Hello it's ClassA”!?
}
#end
thanks in advance for any help :)
It is behaving as expected; you've instantiated an instance of ClassB and, this, when method1 calls [self method2], the method dispatch follows the normal lookup path. self is an instance of ClassB.
Copy/paste this into all your methods:
NSLog(#"%s %p %#", __PRETTY_FUNCTION__, self, self);
That should make it clear what is going on.
any work arounds?
Yes, don't do this as it is poor design. A superclass second guessing inheritance is a sure fire way to end up with an unmaintainable mess of a code base.

Call method with instance creator as receiver

I have class A, (NSDocument subclass) which stores my document data. Class A creates an instance of Class B, (NSView subclass) which manages the view. I want it so that every time the drawRect: method of Class B is called, it calls updateChangeCount: on Class A so that the user will know to save the document.
I'm not completely familiar with OSX projects and what exactly drawRect: does for NSView, so you may want to look into Richard J Ross III's comment. But on the general question of one object calling a method on the object that instantiated it:
ClassB.h
#protocol ClassBDelegate <NSObject>
#reqiured
- (void)someRequiredMethod;
#optional
- (void)someOptionalMethod;
#end
#interface ClassB <NSView>
#property (nonatomic, assign) id<ClassBDelegate> delegate;
// Other stuff you need in your interface
#end
ClassB.m
- (void)someClassBMethodThatNeedsToTriggerSomeClassAMethod {
// stuff
[self.delegate someRequiredMethod];
if ([self.delegate respondsToSelector:#selector(someOptionalMethod)]) {
[self.delegate someOptionalMethod];
}
// stuff
}
Now, in ClassA, be sure you conform to this protocol:
#import ClassB.h
#interface ClassA <ClassBDelegate>
And implement the required method:
- (void)someRequiredMethod {
// stuff
NSLog(#"Hello world!");
// stuff
}
And when you instantiate your ClassB object, be sure to set its delegate to yourself:
classB.delegate = self;
EDIT: Note, I put in an example of how ClassB can use optional methods as well as required methods.

Private methods in objective-c not private

I've created two classes with methods with same name. In one of them it is private, in another - public.
Then somewhere on code i write this:
-(void) doMagic:(id) object {
[(ClassA*)object doSmth];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
ClassB * objB = [[ClassB alloc] init];
[self doMagic:objB];
}
In console i see this:
2012-04-25 23:41:28.183 testmagic[558:403] classB - doSmth
Here's classes' sources:
//.h
#interface ClassA : NSObject
-(void) doSmth;
#end
//.m
#implementation ClassA
-(void)doSmth {
NSLog(#"classA - doSmth");
}
#end
//.h
#interface ClassB : NSObject
#end
//.m
#interface ClassB ()
-(void) doSmth;
#end;
#implementation ClassB
- (void)doSmth {
NSLog(#"classB - doSmth");
}
#end
I know, it's because of "message" nature of methods in Obj-C, and at runtime class possibly do not know which of it's methods are private or public, but here's the question:
How can i make really private method? I heard that with decompiling it's possible to see methods names, so someone can just use my private API. How can i prevent it?
The runtime cannot call what it never knows about. The approach I typically take is to use a static function:
MONObject.h
#interface MONObject : NSObject
// ...
#end
MONObject.m
// 'private' methods and ivars are also visible here
#interface MONObject()
// ...
#end
// typically here:
static void fn(MONObject * const self) {
NSLog(#"%#", [self description]);
}
#implementation MONObject
// ...
// sometimes here:
static void fn2(MONObject * const self) {
NSLog(#"%#", [self description]);
}
#end
A workaround to your problem could be to use a proxy/façade class which internally aggregates an instance of your private class. E.g.:
// .h
#interface FoobarFacade: NSObject
- (void)publicMethod;
#end
// .m
#interface FoobarFacade ()
{
Foobar* impl;
}
#end
#interface Foobar: NSObject
- (void)secretMethod;
#end
#implementation Foobar
- (void)secretMethod { NSLog(#"foobar secret method"); }
#end
#implementation FoobarFacade
- (void)publicMethod {
NSLog(#"façade public method");
[impl secretMethod]; // calling into the secret method
}
#end
Of course this isn't 100% safe either, the runtime puts no barriers as others already told.
Right now you can't have truly private methods. When you are declaring a method in a class extension in the .m file you are just hiding it from being exposed in the public header fle. What you are doing now is considered good design because you are hiding the method from the header file which means people would have to go to some length to find those hidden methods, but they can still find them.
Basically the rule I follow is to put as little as I can into the public header as possible and to put everything else into a class extension. This is all you can really do for now.
If you declare the method in the .h file is public. If you want private visibility you have to declare the method in your .m for example:
#interface ClassB (Private_Methods)
- (void)doSmth;
#end
#implementation ClassB
//Rest of .m

Objective-C inheritance; calling overridden method from superclass?

I have an Objective-C class that has a method that is meant to be overridden, which is uses in a different method. Something like this:
#interface BaseClass
- (id)overrideMe;
- (void)doAwesomeThings;
#end
#implementation BaseClass
- (id)overrideMe {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
- (void)doAwesomeThings {
id stuff = [self overrideMe];
/* do stuff */
}
#end
#interface SubClass : BaseClass
#end
#implementation SubClass
- (id)overrideMe {
/* Actually do things */
return <something>;
}
#end
However, when I create a SubClass and try to use it, it still calls overrideMe on the BaseClass and crashes due to doesNotRecognizeSelector:. (I'm not doing a [super overrideMe] or anything stupid like that).
Is there a way to get BaseClass to call the overridden overrideMe?
What you are describing here should work so your problem is likely elsewhere but we don't have enough information to help diagnose it.
From your description, I'd say either the instance you're messaging is not the class you think it is or you made some typo in your code when declaring the method names.
Run your application under gdb, add a symbolic breakpoint on objc_exception_throw, reproduce your problem. Once your process has stopped on the "doesNotRecognizeSelector" exception, print object description and it's class.
Or log it before calling -overrideMe:
NSLog(#"object: %# class: %#", obj, [obj class])
Write a category for BaseClass to override the method.
#interface BaseClass (MyCategory)
- (id) overrideMe;
#end
#implementation BaseClass (MyCategory)
- (id) overrideMe
{
/* Actually do things */
return <something>;
}
#end
Now all instances of BaseClass will respond to selector overrideMe with the new implementation.

creating instances in objective c

Here is my code:
//ECHOAppDelegate.m
#implementation ECHOAppDelegate
...
#end
//PtyView.m
#interface PtyView (PtyPrivate)
-(void)startTask;
-(void) didRead: (NSNotification *)fileNoty;
#end
#implementation PtyView
...
-(void)startTask {
//starts task
}
#end
Now, how do I trigger "startTask" from ECHOAppDelegate.m? I need to create an instance? I'm a total beginner :D
Any example code would be awesome!
Thanks,
Elijah
-(void)startTask; appears to be private implementation and in theory should not be called from external classes.
To answer your question, you can call it something like this:
PtyView *v = [[PtyView alloc] init];
[v startTask];
[v release];
Though you will get a warning saying, PtyView might not respond to startTask. Since it is not in public interface of class.
Update: Above code assumes that when startTask returns, you are done with this object. But something tells me that you might be using async callbacks. If that is the case then startTask might return immediately and you won't release it then and there. Normally in this case, you will be notified by PtyView about the completion of task. So you release it when the task is complete.
Update2:
Making a method public is easy. You just declare it in the public interface (the header file of class):
//in PtyView.h
#interface PtyView
-(void)startTask;
#end
//in PtyView.m
#implementation PtyView
...
-(void)startTask {
//starts task
}
#end
Notice that there is no category defined in the interface declaration.
self represent the current object.
You just need to call the method like that.
[self startTask];
How about subclassing ECHOAppDelegate? (Then make sure PtyView inherits from NSObject?)
// cf. http://amath.colorado.edu/pub/mac/programs/PseudoTTY.zip
#interface ECHOAppDelegate : PtyView
...
#end
#implementation ECHOAppDelegate
- (id) init
{
self = [super init];
if (!self) return nil;
...
return self;
}
...
[self startTask];
...
#end