Let's say I have class A and class B. In class A I create an instance of class B. Class B has delegate methods that, when called, I want to call instance methods in class A. Is there a way to pass a reference to class A when instantiating class B?
You can use a delegate to return information to the first Class
Class B.h
#protocol delegateB <NSObject>
-(void)doSomething:(NSString *)data;
#end
#interface ClassB : UIViewController
#property(nonatomic, assign) id<delegateB> delegate;
#end
Class B.m
#synthesize delegate = _delegate;
- (void)viewDidLoad {
[_delegate doSomething:#"String to send"];
}
In the class A:
Class A.h
#interface ClassA : UIViewController
-(void)doSomething:(NSString *)data;
#end
Class A.m
When you instance the class, you need to assign self:
ClassB *cb = [[ClassB alloc] init];
cb.delegate = self;
To use the function:
-(void)doSomething:(NSString *)data{
//do something whit the data
}
Add a property of type A to B and assign self to it after initialising. You could also pass self as an argument to the delegate method you mentioned. Actually this is common practice in cocoa (look at UITableViewDelegate)
You can use type Class to pass a reference to a class. For class A use [A class] to get the referenece. But note that with a general class reference you won't be able to simply write [aClassRef aClassMethod], because Class instancce can reference any class (so the compiler don't know if particular method is supported or not).
The actual solution should be closer to what Julian suggests, but maybe this note will be useful in some way too.
Related
I am currently in the process of Learning Objective-C coming from a c++ background. I wanted to know if there was a way for the derived class method that has the same signature as the base class to not override it.
I read that every method in Objective-C is virtual.Are there any ways in which a derived class does not override the base class method be simulated ?
I have the following two classes
#interface foo_base : NSObject
-(void) base_method;
-(void) shared_method;
#end
#interface foo_der : foo_base
-(void) der_method;
-(void) shared_method;
#end
and when I use it like this
foo_base *b = [[foo_der alloc]init];
[b shared_method]; //Derived class method will be called.
I know I could do something like this inside the derived class method
[super shared_method] //call base class method
No, in Objective-C if a derived class implements a base class method with the same signature, it is always overridden. You could create a "helper" function like this if you really want to access the base class method directly.
- (void) callSuperSharedMethod {
[super sharedMethod];
}
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.
I need to move the same method from 4 different classes to the superclass.
Such methods are exactly the same except for the type of a variable declared in them:
For example, in the method in the first class I have
FirstClass var = [[FirstClass alloc] init]
in the second class
SecondClass var = [[SecondClass alloc] init]
and so on.
What's the best way to implement this variation in the superclass ?
Should I use NSClassFromString in the superclass and get each string from each method in the subclasses?
thanks
I'm not 100% sure I get what you mean. So I could be answering the wrong question
If inside your class you need to use an object (I've called it worker below) to do your work, but the class of this object is not known til later, you can use dependency injection (DI).
MyClass.h
#interface MyClass : NSObject
#property (nonatomic, retain) id<WorkerInterface> worker;
#end
MyClass.m
#implementation MyClass
#synthesize worker = _worker;
- (void)myMethod;
{
[self.worker doSomething];
}
// You could also provide a default class to use if one is not passed in
//
// - (id<WorkerInterface)worker;
// {
// if (!_worker) {
// _worker = [[DefaultWorker alloc] init];
// }
// return _worker;
// }
#end
Now whenever I instantiate this class I can simply pass in the appropriate object to be used e.g:
MyWorkerClass *worker = [[MyWorkerClass alloc] init]; // <- Conforms to #protocol(WorkerInterface)
MyClass *instance = [[MyClass alloc] init];
instance.worker = worker;
[instance doSomething];
If all the different types of iVar's you intend on initializing in the subclasses are descended from a common class, then I'd store that class in the super, or else just store it as an id. Then, setup a property accessor in each of your subclasses the casts the iVar as you need it.
#interface superClass : NSObject{
id _superIvar;
}
#end
#implementation superClass : NSObject
....super's code....
#end
Now in the implementation of the subclass declare a property in a category, shown below (or in the interface, if you want it public)
#interface subClass (private)
#property (strong) ClassType *superIvar;
#end;
#implementation
- (void) setSuperIvar:(ClassType *)superIvar{
_superIvar = superIvar;
}
- (ClassType *) superIvar{
return (ClassType *) _superIvar;
}
- (void) someMethodThatUsesSuperIvar{
[self.superIvar doSomething];
}
#end
Alternatively, if you don't want to open your _superIvar to direct access, you can set a property on the superclass and access through the property on the subclass. But in this way you can easily access super's ivars cast to the appropriate type.
Suppose I have Objective C interface SomeClass which has a class method called someMethod:
#interface SomeClass : NSObject {
}
+ (id)someMethod;
#end
In some other interface I want to have a helper method that would dynamically invoke someMethod on a class like this:
[someOtherObject invokeSelector:#selector(someMethod) forClass:[SomeClass class];
What should be the implementation for invokeSelector? Is it possible at all?
- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
// ???
}
Instead of:
[someOtherObject invokeSelector:#selector(someMethod) forClass:[SomeClass class];
call:
[[SomeClass class] performSelector:#selector(someMethod)];
Example (using GNUstep ...)
file A.h
#import <Foundation/Foundation.h>
#interface A : NSObject {}
- (NSString *)description;
+ (NSString *)action;
#end
file A.m
#import <Foundation/Foundation.h>
#import "A.h"
#implementation A
- (NSString *)description
{
return [NSString stringWithString: #"A"];
}
+ (NSString *)action
{
return [NSString stringWithString:#"A::action"];
}
#end
Somewhere else:
A *a = [[A class] performSelector:#selector(action)];
NSLog(#"%#",a);
Output:
2009-11-22 23:32:41.974 abc[3200] A::action
nice explanation from http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html:
"In Objective-C, a class object gets all the instance methods of the
root class for its hierarchy. This means that every class object
that descends from NSObject gets all of NSObject's instance methods -
including performSelector:."
In Objective-C, classes are objects as well. The class objects are treated differently, however, as they can call the instance methods of their root class (NSObject or NSProxy in Cocoa).
So it's possible to use all the instance methods defined in NSObject on class objects as well and the right way to dynamically invoke a class method is:
[aClass performSelector:#selector(aSelector)];
The apple docs are a bit more specific.
You shouldn't implement this yourself.
The NSObject Protocol has a performSelector: method that does exactly this.
Is this built-in method what you want?
id objc_msgSend(id theReceiver, SEL theSelector, ...)
(See the runtime reference docs for this function.)
Example is provided below. If I set
id<RandomProtocol> delegate = [[B alloc] init];
Will doingSomething of class A or class B be called?
A.h
#protocol RandomProtocol
-(NSString*)doingSomething;
#end
#interface A : NSObject <RandomProtocol>
#end
A.m
#import "A.h"
#implementation A
- (NSString*) doingSomething {
return #"Hey buddy.";
}
#end
B.h
#import "A.h"
#interface B : A
#end
B.m
#import "B.h"
#implementation B
- (NSString*)doingSomething {
return #"Hey momma!";
}
#end
To be more clear, class B's implementation of -doingSomething will be called rather than class A's implementation, simply because class B inherits from class A, and never calls super's implementation.
If you would want to call A's implementation from inside B's, you would add in the line [super doingSomething] inside B's -doingSomething method.
As mentioned in the previous answer, the fact that -doingSomething is declared in a protocol is completely irrelevant here, as protocols simply exist for providing compile-time information of what a class is capable of doing, for the developer's own benefit.
Class B's implementation will be used regardless of whether it follows a protocol or not. The message "doingSomething" is sent to a class of type "B" because that's what you allocated, and in class B, "doingSomething" is the first method encountered by the runtime as it progresses its way up the class hierarchy.