Call method with instance creator as receiver - objective-c

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.

Related

How to declare events and delegates in Objective-C?

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..

Subclassing, protocols, and delegates - not calling

I have 2 classes:
#protocol MainProtocol
-(void) method1;
#end
#interface ClassA : NSObject
#property id <MainProtocol> delegate;
#end
and
#protocol SubProtocol <MainProtocol>
-(void) method2
#end
#interface ClassB : ClassA
#end
#implementation ClassB
-(void) foo {
[self.delegate method1]; // works fine
[self.delegate method2]; // error
}
#end
I am not sure why I am unable to call method2 with self.delegate. Is it because delegate is declared in the parent class? If so, how do I localize delegate in ClassB?
Inside -[ClassB foo], self.delegate is declared as type id<MainProtocol> – that is, it conforms to MainProtocol, but not necessarily to SubProtocol. As such, ClassB instances aren't sure that delegate responds to -method2. You can redeclare delegate in ClassB as an object of type id<SubProtocol> if you want to send -method2 to it.

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

How do I call a class function from within an object within the class?

Basically, I want to call a function of a main class within a subclass that the main class holds a pointer to.
I know I can just get the main class to initiate the subclass and attach the function to it. But I do not want that, I want the subclass to initiate itself with its init function.
Is there any way I can call doSomething from someClass?
Some basic code to show what I want:
In MainViewController.h:
#class SomeClass;
#interface MainViewController : UIViewController {
SomeObject *someInformation;
SomeClass *someInstance;
}
#property (nonatomic, strong) SomeClass *someInstance;
-(void)doSomething:(id)sender;
#end
In MainViewController.m:
#implementation MainViewController
#synthesize someInstance;
-(void)doSomething:(id)sender {
//do something to someInformation
}
#end
In SomeClass.h:
#interface SomeClass : NSObject {
UIStuff *outstuff;
}
#property (strong, nonatomic) UIStuff *outstuff;
-(void)somethingHappened:(id)sender;
#end
In SomeClass.m
#implementation SomeClass
#synthesize outStuff;
-(IBAction)somethingHappened:(id)sender {
//call doSomething to the main class that points to this class
}
#end
Your terminology is shaky. Classes do not "hold" other classes. In your case, instances of class MainViewController have pointers to objects of class SomeClass. I am not being pedantic; poor terminology such as this casts doubt on one's understanding of underlying and important concepts.
That said, SomeClass objects need a reference to a MainViewController object if you want a SomeClass object to be able to send a message to a MainViewController instance. From the code you have posted, no such reference exists. You either need to expand the SomeClass interface to store an explicit reference to a MainViewController object, or you can employ something slightly more indirect (at least conceptually) via delegation. However, because you have not provided case-specific information, our solutions will be formed lacking detail-derived insight.

Protected methods in Objective-C

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;