C# code:
public delegate void ItemFound(ChunkDetails ObjChunkDetails);
public event ItemFound eventItemFound;
How to declare the above event delegates mechanism in Objective-C?
I tried to declare delegates method in objective-c but still i need help.
Objective-C:
+ (void) ItemFound:(ChunkDetails *)ObjItemDetails;
So how to declare signature of events and delegates in .h file of Objective-C?
The iOS developer guide has a good section on delegation. But here's a brief example for you. In iOS, you usually declare a protocol for a delegate to implement:
#protocol BatteryMonitorDelegate <NSObject>
- (void)batteryMonitor:(BatteryMonitor *)monitor didUpdateBatteryLevel:(NSNumber *)batteryLevel;
#end
You would then declare a property on your class for your delegate. This property will be for an object of a type that implements the above protocol:
#interface BatteryMonitor : NSObject
#property (nonatomic, weak) id<BatteryMonitorDelegate> delegate;
#end
You'll then implement the protocol in a custom class, to handle any any methods it defines:
#interface SomeClass : NSObject <BatteryMonitorDelegate>
#end
#implementation SomeClass
- (void)batteryMonitor:(BatteryMonitor *)monitor didUpdateBatteryLevel:(NSNumber *)batteryLevel
{
// handle the delegate callback
}
#end
Finally, you can call the delegate method when required, from your original object:
#implementation BatteryMonitor
- (void)someMethod
{
// code
if ([self.delegate respondsToSelector:#selector(batteryMonitor:didUpdateBatteryLevel)])
{
[self.delegate batteryMonitor:self didUpdateBatteryLevel:batteryLevel];
}
}
#end
In the example where class A calls class B to perform an action and then return something we would do this:
Class B's .h, this goes above the #interface
#protocol CLASSBNAMEDelegate <NSObject>
- (void) YOURMETHOD:(id) returnValue
#end
Then under the #interface we add a delegate property:
#property (nonatomic, weak) id < CLASSBNAMEDelegate > delegate;
In class b .m where you want to send a message back to Class A you would:
if ([self.delegate respondsToSelector:#selector(YOURMETHOD:)]) {
[self.delegate YOURMETHOD:value];
}
In Class A, where you use Class B be sure to set the delegate like so:
ClassB *b = [Class B etc....];
[b setDelegate:self];
IN Class A Header make sure you:
#interface CLASSA : NSObject <CLASSBNAMEDelegate>
Then you would need to respond to the selector:
- (void) YOURMETHOD:(id) value{}
Hope this helps...
suppose there are two class named as Sender and Receiver. when class sender makes some event and you want some method to be executed in Receiver. then this is the process:
step 1: declaration of protocol
in Class Sender,
#protocol senderDelegate <NSObject>
- (void) eventProcessed;
#end
step 2: make a property delegate
#property (nonatomic, weak) id <senderDelegate> delegate;
it should be nonatomic and only.
step 3: in class sender only where u want to execute this delegate method, do following things-
if ([self.delegate respondsToSelector:#selector(eventProcessed)]) {
[self.delegate eventProcessed];
}
step 4: now jump in Receiver class, and add delegate like
#interface Receiver : UIViewController <senderDelegate>
and don't forget to import sender class
Step 5: delegate should be set before executing sender class
Sender *obj = [[Sender alloc]init];
[obj setdelegate:self];
step 6: implement your methods
- (void) eventProcessed
{
NSLog(#"enjoying with delegate");
}
i think it is simple and understandable, please let me know if u need any more clarification. Thanks..
Related
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'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
If I have a delegate which resides within its own header file myDelegate.h. Then I have a class (ClassOne) that implements the delegate protocol (therefore implementing the delegate function(s)). Then I create another class (ClassTwo) that has a instance variable of myDelegate. Can I then use this variable to call the function that resides in ClassOne?
Here is the code:
//myDelegate.h
#protocol myDelegate <NSObject>
- (BOOL)myFunction:(NSString*)sString;
#end
//ClassOne.h
#interface ClassOne : NSObject <myDelegate> {
}
- (BOOL)myFunction:(NSString*)sString;
#end
//ClassOne.m
#import "ClassOne.h"
#implementation ClassOne
- (BOOL)myFunction:(NSString*)sString
{
//do stuff
}
#end
//ClassTwo.h
#import "myDelegate.h"
#interface ClassTwo : NSObject {
id<myDelegate> del;
}
#property (nonatomic, retain) id<myDelegate> del;
#end
//ClassTwo.m
#import "ClassTwo.h"
#implementation ClassTwo
- (void)aFunction:(NSString*)string
{
[del myFunction:string];
}
#end
Yes, that is exactly right.
Except myDelegate should be MyDelegate. It's not a syntax error and will execute perfectly, but standard objective-c conventions say that you should never define a delegate with a lowercase first character.
I have the following protocol:
#protocol MyProtocol
#property (nonatomic, retain) NSObject *myProtocolProperty;
-(void) myProtocolMethod;
#end
and I have the following class:
#interface MyClass : NSObject {
}
#end
I have a class extension declared, I have to redeclare my protocol properties here or else I can't implement them with the rest of my class.
#interface()<MyProtocol>
#property (nonatomic, retain) NSObject *myExtensionProperty;
/*
* This redeclaration is required or my #synthesize myProtocolProperty fails
*/
#property (nonatomic, retain) NSObject *myProtocolProperty;
- (void) myExtensionMethod;
#end
#implementation MyClass
#synthesize myProtocolProperty = _myProtocolProperty;
#synthesize myExtensionProperty = _myExtensionProperty;
- (void) myProtocolMethod {
}
- (void) myExtensionMethod {
}
- (void) useMyConsumer {
[[[MyConsumer new] autorelease] consumeMyClassWithMyProtocol:self];
}
#end
MyConsumer will only be called from MyClass, so I don't want any other classes to see that MyClass implements methods on MyProtocol because they aren't public API. Similarly, I don't want MyConsumer to see the class extension within MyClass.
#interface MyConsumer : NSObject {
}
#end
#implementation MyConsumer
- (void) consumeMyClassWithMyProtocol: (MyClass<MyProtocol> *) myClassWithMyProtocol {
myClassWithMyProtocol.myProtocolProperty; // works, yay!
[myClassWithMyProtocol myProtocolMethod]; // works, yay!
myClassWithMyProtocol.myExtensionProperty; // compiler error, yay!
[myClassWithMyProtocol myExtensionMethod]; // compiler warning, yay!
}
#end
Is there any way I can avoid redeclaring the properties in MyProtocol within my class extension in order to implement MyProtocol privately?
What you've been referring to as an "anonymous category" is actually known as a class extension, and is used to declare private functionality in an implementation file. That last part is important, because it means that other classes will not be able to see the declarations that you put into a class extension (and they won't be able to see that your class implements the methods of MyProtocol). This is also probably what is responsible for #synthesize failing without redeclaring the properties.
Instead, declare your conformance to the protocol in the interface of your class, and add whatever methods you want to be public:
#interface MyClass : NSObject <MyProtocol> {
}
// public methods and properties go here
#end
If you add the protocol declaration to your interface, then it also removes the need for your consumer to specify it explicitly. Your consumer method can have the following signature instead:
- (void) consumeMyClassWithMyProtocol: (MyClass *) myClassWithMyProtocol;
EDIT: It sounds like you're looking for a way to selectively expose private functionality. First, I would try to consider a different architecture for what you're trying to accomplish, because what's about to follow is a rather unpleasant solution, and it's generally better OOP if everything is public or private.
With that said, Apple typically solves this problem by having a separate header file for the class in question, which declares the methods that should be visible. So you would have your class interface, in which you expose everything that should be completely public:
// MyClass.h
#interface MyClass : NSObject {
}
#end
And a separate header, in which you declare a category for pseudo-private stuff:
// MyClass+Private.h
#import "MyClass.h"
#interface MyClass (Private) <MyProtocol>
- (void)mySortaPrivateMethod;
#end
MyClass.m would implement everything from those two files, and could still have a class extension:
// MyClass.m
#import "MyClass.h"
#import "MyClass+Private.h"
#interface MyClass ()
- (void)myClassExtensionMethod;
#end
#implementation MyClass
// everything can go here
#end
Then your consumer would include MyClass+Private.h so that it can see the declarations there, and everyone else would simply use MyClass.h.
What is the equivalent to protected methods in Objective-C?
I want to define methods which only the derived classes may call/implement.
You can simulate protected and private access to methods by doing the following:
Declare your private methods in a class extension (i.e. a unnamed category declared near the top of the class' .m file)
Declare your protected methods in a Subclass header – Apple uses this pattern with respect to UIGestureRecognizer (see documentation and reference to UIGestureRecognizerSubclass.h)
These protections are not, as Sachin noted, enforced at runtime (as they are in Java, for example).
You can neither declare a method protected or private. Objective-C's dynamic nature makes it impossible to implement access controls for methods. (You could do it by heavily
modifying the compiler or runtime, at a severe speed penalty, but for obvious reasons this is not done.)
Taken from Source.
Here is what I did to get protected methods visible to my subclasses, without requiring them to implement the methods themselves. This meant I didn't get compiler warnings in my subclass about having an incomplete implementation.
SuperClassProtectedMethods.h (protocol file):
#protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
#end
#interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
#end
SuperClass.m: (compiler will now force you to add protected methods)
#import "SuperClassProtectedMethods.h"
#implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
#end
SubClass.m:
#import "SuperClassProtectedMethods.h"
// Subclass can now call the protected methods, but no external classes importing .h files will be able to see the protected methods.
I just discovered this and it works for me.To improve upon Adam's answer, in your superclass make an implementation of the protected method in .m file but don't declare it in .h file. In your subclass make a new category in your .m file with the declaration of the protected method of the superclass and you can use the protected method of the superclass in your subclass. This will not ultimately prevent the caller of the supposedly protected method if forced at runtime.
/////// SuperClass.h
#interface SuperClass
#end
/////// SuperClass.m
#implementation SuperClass
- (void) protectedMethod
{}
#end
/////// SubClass.h
#interface SubClass : SuperClass
#end
/////// SubClass.m
#interface SubClass (Protected)
- (void) protectedMethod ;
#end
#implementation SubClass
- (void) callerOfProtectedMethod
{
[self protectedMethod] ; // this will not generate warning
}
#end
Another way using #protected variables.
#interface SuperClass:NSObject{
#protected
SEL protectedMehodSelector;
}
- (void) hackIt;
#end
#implementation SuperClass
-(id)init{
self = [super init];
if(self) {
protectedMethodSelector = #selector(baseHandling);
}
return self;
}
- (void) baseHandling {
// execute your code here
}
-(void) hackIt {
[self performSelector: protectedMethodSelector];
}
#end
#interface SubClass:SuperClass
#end
#implementation SubClass
-(id)init{
self = [super init];
if(self) {
protectedMethodSelector = #selector(customHandling);
}
return self;
}
- (void) customHandling {
// execute your custom code here
}
#end
You can define the method as a private method of the parent class and can use [super performSelector:#selector(privateMethod)]; in the child class.
You can sort of do this with a category.
#interface SomeClass (Protected)
-(void)doMadProtectedThings;
#end
#implementation SomeClass (Protected)
- (void)doMadProtectedThings{
NSLog(#"As long as the .h isn't imported into a class of completely different family, these methods will never be seen. You have to import this header into the subclasses of the super instance though.");
}
#end
The methods aren't hidden if you import the category in another class, but you just don't. Due to the dynamic nature of Objective-C it's actually impossible to completely hide a method regardless of a calling instance type.
The best way to go is probably the class continuation category as answered by #Brian Westphal but you'll have to redefine the method in this category for each subclassed instance.
One option is to use class extension to hide methods.
In .h:
#interface SomeAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
In .m:
#interface SomeAppDelegate()
- (void)localMethod;
#end
#implementation SomeAppDelegate
- (void)localMethod
{
}
#end
I usually name protected method with internal prefix:
-(void) internalMethod;