Given (id <MyDelegate>)delegate, can you tell what kind of class delegate is? - objective-c

When passing a delegate to MyClass like this,
- (MyClass *)initWithDelegate:(id <MyDelegate>)delegate {..}
is it somehow possible to tell what kind of class my delegate is? Being defined as id, delegate doesn't seem to respond to any method calls like class, description, respondsToSelector etc.
I'd like to be able to track who is calling MyClass!
Thanks in advance!
/Christian

You can call [delegate class]; to get the class of the delegate.
If delegate doesn't respond to that, that means it is nil.
Edit
Now that you mention that you get compiler errors, then your delegate doesn't conform to the protocol NSObject. So the compiler doesn't recognize it as an NSObject. You should modify the declaration of your protocol MyDelegate to the following:
#protocol MyDelegate <NSObject>
// ...
#end

In the case when you can't modify the protocol itself, you could simply write:
- (MyClass*) initWithDelegate:(id<NSObject, MyDelegate>)delegate {..}
Then the 'class' property will be available. You can replace NSObject (or add additional protocols) to support (and thus require the argument to be of) other types. For example:
- (MyClass*) initWithDelegate:(id<NSObject, NSCoding, MyDelegate>)delegate {..}

Related

Are delegate methods privately declared?

In my view controller's viewDidLoad method, I create an NSURLConnection
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest
delegate:self]
You can see I set the delegate to self.
Then I implemented the delegate method
-(void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) reponse {
//myImplementation;
}
This implementation is only defined in the #implementation ViewController #end block, and it is not declared in the ViewController's #interface.
So I guess this method is private? It compiles and runs well. But I just can't call this method like [self connection: connection didReceiveResponse: response] in the ViewController's own methods.
What's the explanation?
The methods are declared via your inclusion of the NSURLConnectionDelegate protocol in the class's interface definition:
#interface MyViewController : UIViewController <NSURLConnectionDelegate>
This tells the compiler that your class promises to implement all the required methods of that protocol, and that it may implement the optional methods (as it happens, this particular protocol has only optional methods). So the declarations exist publicly, they're just in another file.
The method is "private" inasmuch as it is possible to have a private method in Objective-C. You actually can call the method from outside of the class, even if it's not declared in the interface. This is possible by way of Objective-C's dynamism in how it handles method calls -- any object can receive any message (the obj-c lingo for method), but whether or not the object can actually do something with that method depends on any number of things. Check out Object Messaging in Apple's docs.
The short answer is that your code works as you have it because an implementation of your method exists in your class, and Objective-C knows how to find it at runtime regardless of your class interface.

Exposing/Synthesizing iVar properties in Objective c

I have a class that essentially acts as a light weight wrapper class around another class. It holds that other class as an iVar. I want to be able to expose certain properties (quite a few actually) of the iVar, but to do so I have to write out each property accessor like so:
- (void) setProperty:(Class *)value{
_iVar.property = value;
}
- (Class *) property{
return _iVar.property;
}
Of course, I have to do this for every single property, which is a pain (there are about 30 of them). I would love to be able to synthesize this but I haven't been able to figure out how.
Is it possible to synthesize?
Also, I can't subclass....well, I might be able to but it's really not recommended. The iVar class is really quite heavy (it implements CoreText). I'd rather write out the methods by hand.
Ok, so here's the solution I found...ended up being pretty simple once you knew what to do. First overwrite '- (id) forwardingTargetForSelector:(SEL)aSelector' and return the iVar:
- (id) forwardingTargetForSelector:(SEL)aSelector{
return iVar;
}
When the runtime is looking for a method and cannot find one, it will call this method to see if there is another object to forward the message to. Note that this method normally returns nil and if you return nil here, your program will crash (which is the appropriate behavior).
The second part of the problem is to shush the compiler errors/warnings you'll get when you try to send a message that's not declared. This is easily done by declaring a category you don't implement.
#interface Class (iVarClassMethods)
#propoperty (strong) Class *property1;
......more properties
#end
As long as you don't put in an implementation anywhere, aka #implementation Class (category), the compiler won't complain (it'll assume that the implementation is somewhere....).
Now the only drawback I see is if you change any of the properties in the interface of the iVar Class, you need to make sure you update all other classes that use the method described above, otherwise you'll crash when another class tries to send what is now the wrong method (and the compiler won't warn you beforehand). However, this can be gotten around. You can declare protocols in a category. So instead you create a separate protocol for the iVar class and move the methods/properties you wish out of the iVar class into the protocol.
#protocol iVarClassProtocol
#propoperty (strong) Class *property1;
......more properties
#end
Add that protocol to the iVar subclass so it has those methods declared through the protocol now.
#interface iVarClass <iVarClassProtocol>
....other methods/properties you don't need forwarded
#end
Finally, simply add the protocol to the category. So instead of the aforementioned category with explicit declarations you'll have:
#interface Class (iVarClassMethods) <iVarClassProtocol>
#end
Now, if you need to change any of the to-be-fowarded properties/methods, you change them in the protocol. The compiler will then warn you when you try to send the wrong method to the forwarding class.
I think you can forward the messages to the ivar:
- (void) forwardInvocation: (NSInvocation*) invocation
{
[invocation invokeWithTarget:ivar];
}
- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector
{
NSMethodSignature *our = [super methodSignatureForSelector:selector];
NSMethodSignature *ivars = [ivar methodSignatureForSelector:selector];
return our ? our : ivars;
}
Then you have to hide or fake the type of your object, for example by casting to id, otherwise the compiler will complain that your class does not implement those methods.
Of course it would be best if you could come up with some better design that would do without such tricks.

How to call a delegate's function without getting the "instance method not found" warning in ios?

In the apps I worked on, I often found such lines of code
[delegate aFunction];
that generated the "instance method "aFunction" not found (return type defaults to id)" warning
Now, I did a bit of research on SO and found out that the warning can be removed by declaring the function for cases when you call it on self ([self aFunction];), but none of the answers said anything about my case, when I use a delegate.
So, long story short, what can I do to correctly call a delegate's method inside another class?
Things appear to work fine, so this is not a major issue, but a warning means I'm not doing something completely correct so I would like to learn what's the best practice for such cases
Thank you for your help in advance!
So, if I'm understanding you correctly, your issues can be taken away by declaring your protocol as follows:
#class SomeClass;
#protocol SomeClassDelegate <NSObject>
#required
- (void)thisObjectDidSomething:(SomeClass*)instance;
#optional
- (void)thisObjectDidSomethingUnimportant:(SomeClass*)instance;
#end
Then your delegate ivar and property look like this (use assign instead of weak if you're not using ARC):
#interface SomeClass () {
__weak id<SomeClassDelegate> delegate_;
}
#property (weak) id<SomeClassDelegate> delegate;
And in the .h file of any class that's going to implement that protocol, do this:
#interface TCReader : NSObject <SomeClassDelegate> {
}
Since it's safe to call selectors on nil, for required methods, you can just:
[self.delegate thisObjectDidSomething:self]
But for optional methods, you'd better:
if ([self.delegate respondsToSelector:#selector(thisObjectDidSomethingUnimportant:)]) {
[self.delegate thisObjectDidSomethingUnimportant:self]
}
The main point here is that by declaring and making use of a protocol, you let XCode know that those methods are defined for objects implementing the protocol. If you require that your delegate implement that protocol, then Xcode knows that your delegate has those methods defined.

How to create a delegator in objective C?

I am trying to learn, how to implement delegation pattern in objective C. But the discussion almost exclusively concentrates on the adoption of protocols and then implementing the delegate methods that come with particular protocol - or - the delegation principle alone - or protocols alone.
What I am unable to find, is a easy to understand material about how to write a class that will serve as a delegator. By that I mean the class, which the message of some event will come from and which will provide the protocol for receiving that message - kind of 2in1 description. (protocols and delegation).
For the purpose of my learning, I'd like to go along the following trivial example, using an iPhone, a Cocoa touch application and Xcode4.2, using ARC, no Storyboard or NIBs.
Let's have a class with name "Delegator", which is a subclass of NSObject. The Delegator class has NSString instance variable named "report" and adopts the UIAccelerometerDelegate protocol.In the Delegator implementation, I will implement the the delegate method
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
This delegate method will create a NSString #"myReport" and store it in the report variable anytime there is an accelerometer event. Further, I want to have a second class named ReportsStorage (a subclass of NSobject), which can store some Nsstring (report) in its instance variable called latestReport.
So far so good.
Now lets get back to theDelegator Class. I'd like to implement a protocol in Delegator named ReportsDelegate which will notify the class that adopts it (the ReportsStorage class), that a report was generated and will pass this report through the delegate method, which should be (I believe) something like this
-(void)delegator:(Delegator *)delegator didCreateNewReport:(NSString *)report;
Can you please provide the code for Delegator Class (incl. the "delegate" property), that will achieve this, with a description what each line of code means?
Thanks in advance, EarlGrey
You'll need to declare the delegate property as an id<ReportsDelegate> type. That is, any object type (id) conforming to the ReportsDelegate protocol (<ReportsDelegate>). Then, if the delegate method is considered optional, check if the delegate responds to that selector before calling it. (respondsToSelector:).
Like so:
Delegator.h
#import <Foundation/Foundation.h>
// Provide a forward declaration of the "Delegator" class, so that we can use
// the class name in the protocol declaration.
#class Delegator;
// Declare a new protocol named ReportsDelegate, with a single optional method.
// This protocol conforms to the <NSObject> protocol
#protocol ReportsDelegate <NSObject>
#optional
-(void)delegator:(Delegator *)delegator didCreateNewReport:(NSString *)report;
#end
// Declare the actual Delegator class, which has a single property called 'delegate'
// The 'delegate' property is of any object type, so long as it conforms to the
// 'ReportsDelegate' protocol
#interface Delegator : NSObject
#property (weak) id<ReportsDelegate> delegate;
#end
Delegator.m
#import "Delegator.h"
#implementation Delegator
#synthesize delegate;
// Override -init, etc. as needed here.
- (void)generateNewReportWithData:(NSDictionary *)someData {
// Obviously, your report generation is likely more complex than this.
// But for purposes of an example, this works.
NSString *theNewReport = [someData description];
// Since our delegate method is declared as optional, check whether the delegate
// implements it before blindly calling the method.
if ([self.delegate respondsToSelector:#selector(delegator:didCreateNewReport:)]) {
[self.delegate delegator:self didCreateNewReport:theNewReport];
}
}
#end

Does Objective-C have something like C++ virtual functions?

In objective-c it is possible to add a #dynamic to a property.
Is this also possible for normal instance methods?
EDIT
I think i wasn't clear enough.
I want to do the following:
#interface MyClass
#property (retain) NSObject *somePropertyObject;
- (void) myMethod;
#end
#implementation MyClass
#dynamic somePropertyObject;
//Make myMethod dynamic. I do not want to implement it. Like C++ Virtual
#end
If you mean "How can I declare a method, but not provide a definition which I will subsequently provide at runtime?" Then it's easy, just use a category. Like this:
#interface MyObject : NSObject
// Methods I'll define
- (void)doFoo;
#end
#interface MyObject (DynamicallyProvidedMethods)
// Methods I won't
- (void)myDynamicMethod;
#end
#implementation MyObject
// Methods I'll define
- (void)doFoo
{
}
#end
The compiler will not complain, however if you call -myDynamicMethod at runtime, unless you have provided an implementation for it somehow, it will crash with "unrecognized selector." You can, of course, test for that at runtime by calling respondsToSelector:.
Relatedly, if you're looking to do a near-equivalent of a base class pure virtual method, I would recommend providing an empty implementation that asserts when called if it has not been overridden by a subclass. You can do that like so:
NSAssert((class_getInstanceMethod([self class], _cmd) == class_getInstanceMethod([MyObject class], _cmd)),
#"Subclass of %# must override -%#",
NSStringFromClass([MyObject class]),
NSStringFromSelector(_cmd));
// ...where overridesSelector:ofBaseClass: looks like:
//
// return ;
Of course, that won't alert you to problems at compile time, but it's better than nothing.
HTH
I think you might be asking how to declare a method that will be implemented some time later somewhere else.
The Objective-C way to do that is to use Protocols.
You declare a protocol like this, usually in a header file
#protocol MyProtocol <NSObject> {
#optional
- (void)optionalMethod;
#required
- (void)requiredMethod;
}
#end
This declares two methods, one which is optional and one is required. To use this protocol you declare the conformance when declaring the class that will implement the protocol
#interface MyConformingClass : NSObject <MyProtocol> {
}
// you don't have to redeclare methods that are declared in the protocol
#end
This new class is checked at compile time for the implementation of requiredMethod so it has to implement it, but it can choose whether or not to implement the optionalMethod
Now, any class that requires instances of objects to conform to the protocol can declare this, for example, in the interface
#interface RequiringClass : NSObject {
MyConformingClass <MyProtocol> *conformingClassObject;
}
…
#end
Again, this is checked at compile time
To make sure that the conforming class implement the #optional methods, we can use this handy structure
if [conformingClassObject respondsToSelector:#selector(optionalMethod)] {
[conformingClassObject optionalMethod];
} else {
// Do something here because the optional method isn't provided
}
Examples of this are all over Cocoa - it's a class can provide a list of actions that it would like to farm out to it's delegate, the delegate adopts the protocol and provides the implementations of those delegate methods. The calling object can then check if this delegate responds to those methods at runtime as I've described above, and call those methods to perform actions, or provide information where ever it needs to.
This is used quite a lot in Objective-C, where classes provide a list of methods that they would like some other class to perform, unlike virtual functions, where a class declares functions it wants subclasses to provide implementations for. Particularly as Composition is favoured over inheritance in the language. Rather than create a subclass to provide an implementation, you just create another class that can do the same thing, and add a reference to that in the class instead.
No.
#dynamic is just an instruction to the compiler that says: "Don't bother generating accessors for this property, I'm going to provide my own."
Using #dynamic with other methods wouldn't be helpful because the compiler doesn't generate any methods other than accessors for you, and of course you're supplying the other methods anyway.
What are you trying to accomplish?