Subclassing, protocols, and delegates - not calling - objective-c

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.

Related

Call method with instance creator as receiver

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.

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

Calling instance method to access IBOutlet instance from another class

I've been searching through a lot of forum but it's still driving me crazy.
i don't understand how to access IBOutlet instance for example of class 'A' from class 'B' which is attempting to change the value let's say the instance type is IBOutlet NSTextLabel *progressStatus with stringValue "Capturing" want to change to "Recognizing". It can be called only from the instance method of classA it self, but not from another class.
#interface classA : NSView
{
NSTextField *progressStatus;
}
#property (assign) IBOutlet NSTextField *progressStatus;
-(void)recognizeStatus;
#end
#import "classA.h"
#implementation classA
#synthesize progressStatus;
-(void)awakeFromNib
{
[self recognizeStatus]; //successfully change the value inside progressStatus
}
-(void)recognizeStatus
{
[progressStatus setStringValue:#"Recognizing"];
NSLog(#"Progress Status : %#",progressStatus.stringValue);
}
- (void)captureOutput:(QTCaptureOutput *)captureOutput didOutputVideoFrame:(CVImageBufferRef)videoFrame withSampleBuffer:(QTSampleBuffer *)sampleBuffer fromConnection:(QTCaptureConnection*)connection
{
//code to convert videoFrame to IplImage type named frameImage
BOOL faceDetected = [classB faceDetection:frameImage];
}
#end
#import "classA.h"
#interface classB : NSObject
{
}
+(BOOL)faceDetection:(IplImage*)source;
#end
#import "classA.h"
#import "classB.h"
#implementation classB
+(BOOL)faceDetection:(IplImage*)source
{
classA *status = [[classA alloc] init];
[status recognizeStatus]; //no changes with the value inside progressStatus
//return bool type
}
#end
In classB's class method faceDetection:you initialize an instance of classA which derives from NSView, but you do not add the instance to the view hierarchy. Further, in initializing the instance of classA you aren't loading the view from a nib, so the instance of classA status likely has a nil progressStatus.
I suspect you may be trying to access an instance of classA that was already initialized and added to the view hierarchy elsewhere; but initializing another instance won't provide you with a reference to the original instance.

Objective-C calling a delegate method from a class where the delegate method resides within another class

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.

Objective C: use instance class in other class

In my code, in an class I have an ivar
FirstClass *first;
and I can use first within an instance of this class.
But if I want to access first from another object instance (or even another class), how can I do that?
I assume you're talking about using FirstClass in another source file than its own, right?
In this case you'd have to import its header by adding this to the top of your second class' ".m"-file:
#import "FirstClass.h"
If you also need to reference in your second class' header ".h"-file, then you can add a
#class FirstClass;
before the #interface block. This will tell the compiler that it should consider a class of that name to be existant, but to not bother you with warnings unless you forget to import the given first class' ".h" file in the second class' ".m" file.
To allow access from foreign objects to your SecondClass' firstClass iVar you'll need to implement a getter method for firstClass.
This is done with
#property (nonatomic, readwrite, retain) FirstClass *firstClass;
in the #interface block, and
#synthesize firstClass;
in the #implementation block.
With this set up you can then either call [secondClassInstance firstClass]; or access it via the dot syntax secondClassInstance.firstClass;.
My sample will also synthesize a setter method called setFirstClass:. To make the property read-only, change readwrite to readonly in the #property declaration.
Sample:
FirstClass.h:
#import <Cocoa/Cocoa.h>
#interface FirstClass : NSObject {
#private
}
//method declarations
#end
FirstClass.m:
#import "FirstClass.h"
#implementation FirstClass
//method implementations
#end
SecondClass.h:
#import <Cocoa/Cocoa.h>
#class FirstClass;
#interface SecondClass : NSObject {
#private
FirstClass *firstClass;
}
#property (nonatomic, readwrite, retain) FirstClass *firstClass;
//method declarations
#end
SecondClass.m:
#import "SecondClass.h"
#import "FirstClass.h"
#implementation SecondClass
#synthesize firstClass;
- (id)init {
if ((self = [super init]) != nil) {
firstClass = [FirstClass alloc] init];
}
return self;
}
- (void)dealloc {
[firstClass release];
[super dealloc];
}
//method implementations
#end
I would use a property. Probably in your header of your second class something like
#property (nonatomic, retain) FirstClass *first;
and in your implementation
#synthesize first;
Than when you create an object of your SecondClass
SecondClass *second = [[SecondClass alloc] init];
you can use
second.first