using Delegate and its selector - iphone

I have a certain scenario where I am trying to accomplish more generic approach of using delegate and calling a selector based on what selector is being set.
For example below is the code:
#protocol HttpRequestDelegate
#optional
- (void)testDrive:(NSData*)dataembedd;
#end
- (id)init {
self = [super init];
if (self) {
//Initialize it here.
self.HttpRequestdelegate = self;
}
return self;
}
HttpRequest *apiCaller = [[HttpRequest alloc] init];
NSLog(#"%#",apiCaller.HttpRequestdelegate);
[WLCC_ApiCaller executeAsync:apiCaller.HttpRequestdelegate :#selector(testDrive:) :[NSURL URLWithString:updateUrl] :wlcc_Get];
However at executeAsync call I am trying to call the selector which is test drive like:
[delegate performSelector:#selector(selector) withObject:responseData];
but it gives me an error of unknown selector, however when I notice the reference of the delegate its the same when initialized.
I am trying to utilize delegate perform selector in different class, is there anything else besides that I need to do here?
Thanks.

Define your protocol like this:
#protocol HttpRequestDelegate <NSObject>
There is an NSObject class and an NSObject protocol. All of your protocols should conform to the NSObject protocol. This gives you methods like respondsToSelector: and others.

I suppose it should be; as what it seems that you're implementing the functions in other and try to call from that place which not inherited the delegate and, possible miss that particular function implementation.
Normally, the delegate pattern is used so we can implement the function according to our need (or can say provide callback) but that class must conform that delegate.Have you checked for it?
Please elaborate more about your implementation as I think so many info are behind the curtains like : WLCC_ApiCaller executeAsync,etc.

Related

Swift super initializer

In Swift, super's initializer should be called after all properties of the current class have been initialized. This is however not done for Objective-C init, where super init is called first before initializing properties in the current class.
What issues is Swift trying to prevent by enforcing this? Why is Objective-C able to avoid the issues Swift is trying to prevent?
What issues is Swift trying to prevent by enforcing this?
This is a great question, and Objective-C did not avoid it.
The problem is that while you're inside an initializer method, the object is technically in a partially constructed state. Bryan's post is a great (albeit contrived) example of why. The general issue is that if a super class's initializer invokes a method, a subclass may have overridden this method. That, in and of itself, is not a bad thing. The problem arises if the overridden method assumes that the object is totally constructed.
However, since the object is still in the midst of invoking the initializers, that is not the case. The object is not wholly constructed until the call to [super init] returns and the class of the object executes any of its initialization code.
There's a related problem with dealloc methods: if you invoke methods inside your -dealloc method, those methods may assume that the object is wholly constructed, when in fact it may be partially deconstructed. This isn't as big of a deal under ARC, but it can still lead to some very subtle bugs.
With Swift, the decision was made to avoid these class of problems by enforcing this rule:
By the time you decide to call super, the calling class must have finished any class-specific initialization.
A variant of this rule is:
You may not invoke methods until after you have called super's initializer.
With this rule, you will never run into the problem described above.
ObjC does not avoid anything.
For this ObjC code, it crashed because parent class is trying to access ivar from child class. It can be detected/avoid if the Swift rule is used. i.e. initialize all members before [super init]
#interface Parent : NSObject
#property (readonly) int value;
#end
#implementation Parent
- (id)init {
self = [super init];
if (self) {
NSLog(#"%d", self.value); // call a method, which can be overrided by child class
}
return self;
}
- (int)value {
return 42;
}
#end
#interface Child : Parent
#end
#implementation Child {
int *_valuePtr;
}
- (id)init {
self = [super init]; // call self.value
if (self) {
// to avoid crash, move this line before [super init], but it may have other undesired effect. e.g. when [super init] return another instance
_valuePtr = calloc(sizeof(int), 1);
}
return self;
}
- (void)dealloc {
free(_valuePtr);
}
- (int)value {
return *_valuePtr;
}
- (void)setValue:(int)value {
*_valuePtr = value;
}
#end

How does respondsToSelector behave when there is a delegate present?

I recently tried to subclass UITextField and set the delegate to myself (found this trying ti solve my problem: http://www.cocoabuilder.com/archive/cocoa/241465-iphone-why-can-a-uitextfield-be-its-own-delegate.html)
#interface MyObject :UITextField <UITextFieldDelegate>
#end
#implementation MyObject
-(id) initWithFrame:(CGRect) frame
{
if((self=[super initWithFrame:frame]))
{
self.delegate=self;
}
return self;
}
-(BOOL) respondsToSelector:(SEL)selector
{
NSLog(#"responds to selector");
return [super respondsToSelector:selector];
}
// Implement all the missing methods
#end
Calling a method defined on the interface results in an infinite recursion. I don't see anything in the Apple docs that defines how respondsToSelector is supposed to behave in the presence of a delegate.
The docs for respondsToSelector states the following:
You cannot test whether an object
inherits a method from its superclass
by sending respondsToSelector: to the
object using the super keyword. [..]
Therefore, sending respondsToSelector:
to super is equivalent to sending it
to self. Instead, you must invoke the
NSObject class method
instancesRespondToSelector: directly
on the object’s superclass
It seems that this could be the cause for your recursion problem. I don't know if the delegate stuff is even related. Just a guess though.

iPhone - how do I know if a protocol method was implemented?

I have created a class and this class has its own delegate protocol.
Inside that protocol, there's an optional method, declared like
#protocol myClassDelegate <NSObject>
#optional
- (void) myOptionalMethod;
#end
Inside the class I have a call to myOptionalMethod, in the form of
[delegate myOptionalMethod];
but as the method is optional, if I call this method on a delegate that has not implemented the method, it will crash.
So, how do I test to see if the method was implemented before calling it?
thanks.
This is pretty easy.
if([delegate respondsToSelector:myOptionalMethod]){
// You can now call this method without a crash
[delegate myOptionalMethod];
}
-respondsToSelector: is useful for individual methods, as others have posted here. For a stricter interpretation, you can see whether a class was declared as implementing a protocol with the -conformsToProtocol: method:
BOOL isAGrommet = [myObject conformsToProtocol: #protocol(Grommet)];
You should use the respondsToSelector method to determine if the delegate has the relevant method prior to calling the selector on the delegate.
For example:
if([delegate respondsToSelector:#selector(myOptionalMethod)]) {
[delegate myOptionalMethod];
}

cocoa - referencing a method on the parent

I had a method on my main view controller named "calculateThis".
This method was run, obviously, as
int newValue = [self calculateThis:myVariable];
when I run it from inside the view controller.
Then I created a static class and I need to run this method from there.
How do I reference this method from that class using just relative references, as super, superview, delegate, etc. I cannot use the class name defined on the delegate because this static class is used in several apps of mine.
I need to go up in the hierarchy, I imagine one level, and access the method there...
thanks.
Define your utility methods in a category on NSObject or related subclasses of NSObject.
Which you have done.
Adding (id)sender to your method will work. Then your method can reference the object that called it. Something like this.
+(int)calculateThis:(id)sender userInfo:(id)info;
then your call becomes.
int newValue = [NSObject calculateThis:self userInfo:myVariable];
If your intent is to create a class that you can use without initializing it, that's possible using class methods. For instance, if I want to make a class called MyClass with a doSomethingWith: method, I would define the following:
In MyClass.h:
#interface MyClass : NSObject {
}
+(void)doSomethingWith:(id)thisObject;
#end
In MyClass.m:
#import "MyClass.h"
#implementation MyClass
+(void)doSomethingWith:(id)thisObject
{
// Your code goes here.
}
#end
To reference this method in another class, you can use the class object for MyClass like so:
[MyClass doSomethingWith:#"Hello, World!"];
This isn't really a typical Cocoa or Cocoa Touch design pattern, but can be handy for things like calculations.
Are you talking about the superclass? If so, you use [super ...].

Accessing Method from other Classes Objective-C

Looked for an answer for this question, but I haven't found a suitable one yet. I'm hoping you guys (and gals) can help me out! (This is for an iPhone app)
Alright, I have a Mutliview application. Each view has it's own class, and everything is happy. However, the different classes sometimes call the same method. Up until now, I have simply wrote that Method twice, in both of the class files.
This is what I want to do though:
I want to make a new class, in It's own file, that has all the "Common" Methods. Then, whenever another class needs to call the Method, I simply call it from the other file. This way, when I want to change the Method, I only need to change it in one place, and not all the places...
I'm not sure how I'd do this, which is why I'm asking for help. I'm a little rusty and new for Objective-C, so pretty examples will help me a lot. Allow me to give you one.
File: ViewController1.m
#implementation ViewController1
//Do Some awesome stuff....
CALL "CommonMethod" HERE
#end
File: ViewController2.m
#implementation ViewController2
//Do Some awesome stuff....
CALL "CommonMethod" HERE
#end
File: CommonClass
#implementation commonClass
- (void)CommonMethod:(id)sender
{
//So some awesome generic stuff...
}
#end
I feel like I need to #import the other file, make an Object from the class and call the Method from the Object... How do I do that?
Thanks again!
Option 1:
#implementation commonClass
+ (void)CommonMethod:(id)sender /* note the + sign */
{
//So some awesome generic stuff...
}
#end
#implementation ViewController2
- (void)do_something... {
[commonClass CommonMethod];
}
#end
Option 2:
#implementation commonClass
- (void)CommonMethod:(id)sender
{
//So some awesome generic stuff...
}
#end
#implementation ViewController2
- (void)do_something... {
commonClass *c=[[commonClass alloc] init];
[c CommonMethod];
[c release];
}
#end
Option 3: use inheritance (see Mr. Totland's description in this thread)
#implementation commonClass
- (void)CommonMethod:(id)sender
{
//So some awesome generic stuff...
}
#end
/* in your .h file */
#interface ViewController2: commonClass
#end
naturally you always need to #import commonClass.h in your view controllers..
There are some answers here telling you to create a common "parent" class. However I think that you can do a lot better. Create a category for UIViewController instead. You don't know all of the internals of what is going on with UIViewController so I don't think it is worth creating your own View Controller hierarchy off of. In fact it could be dangerous. I ran into a number of problems when I tried to create a "base" UITableViewController and then create classes that inherit from that. I avoided these problems by using categories instead.
Your #1 priority shouldn't be inheriting things for no good reason, it should be getting an app into the app store that people will want to download.
It sounds to me like the common code doesn't need to be in a class at all. Is there a reason you can't just use a C-style function for what you want to do?
You could put the common code in a class and then make your other two classes subclasses of that one; this method also avoids the code duplication.
Another option might be to write a class method instead of instance methods for this common code. I think most people feel that singletons are best avoided as a design choice.
It would be easier to give a good answer if we knew more about what you were really trying to accomplish.
What you want to do is to make the two controllers share a common superclass:
UIViewController : MyAwesomeViewController : ViewController1
: ViewController2
commonMethod: would then reside in MyAwesomeViewController. Also, don't start method names with capital letters. :)
To elaborate:
+#interface MyAwesomeController : UIViewController {
-#interface ViewController1 : UIViewController { // and ditto for ViewController2
+#interface ViewController1 : MyAwesomeController {
Bear in mind that Objective-C is just a superset of C, and that whilst #include directives are mostly used for header files, there's nothing stopping you using a #include to embed the contents of one implementation inside another implementation. If the code is truly identical, you can easily just stick it in its own file, and #include it in the .m file.
Having said that, perhaps it would be better to use this technique in conjunction with categories, especially if the same implementation has similar behaviours.
Pass in a reference to your commonClass when you alloc and init your views...
CommonClass *cc = [[CommonClass alloc] init];
ViewController1 *vc1 = [[ViewController1 alloc] ... initWith:cc];
ViewController2 *vc2 = [[ViewController2 alloc] ... initWith:cc];
but making a classic c include might suffice.
As an iPhone neophyte with a Java background and little C, I had a similar problem wishing to refer to a method in both the RootController and a ViewController. It seemed to me that the proper place for the method was the AppDelegate class, an instance of which one obtains in other classes by:
MyAppDelegate *delegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
then if the method is "doSomething" one accesses it by:
[delegate doSomething];
But perhaps this is too obvious or not what was required.
Another method that you can use
#interface ServerManager : NSObject
+(ServerManager *)getInstance;
#implementation ServerManager
+(ServerManager *)getInstance
{
static ServerManager *objServerManager = nil;
if(objServerManager==NULL){
objServerManager=[[self alloc] init];
}
// Return the servermanager object.
return objServerManager;
}
Call Whether you want to use
ServerManager *SMObject = [ServerManager getInstance];
Don't forget to import servermanager.h file.