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

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.

Related

How to change a property class in sub class in Objective-C

I am trying to re-write some code of old project, and ideally I want to achieve below code style, but I got a lot of compile error saying dataModel don't have getLineColor method.
The abstract question is, can I change an inherited object A's class in sub view controller to a sub class A2, while the object A in parent view controller is class A1 that is the super class of A2, and how can I do it correctly? Thank in advance.
Update: I compile it, but I have met another run time error, I tried to overwrite the setter of dataModel in sub view controller. How to correctly write the setDataModel in sub class?
#implementation SubViewController
#pragma mark - setter of dataModel
- (void)setDataModel:(ChartModel *)dataModel { // it stucks at this func name
#end
error trace is
[SubChartViewController setDataModel:](self=0x00000000, _cmd=0x00000000, dataModel=0x00000031) + 12 at BDPAxisChartViewController.m:295, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0xbf774ffc)
EDIT:
#interface ChartModel : NSObject
-(BOOL)chartModelhasData;
#end
#interface LineChartModel : chartModel
-(void)getLineColor;
#property (nonatomic, strong) NSArray* seriesNameArray;
#end
#interface ChartViewController: UIViewController
#property (nonatomic, strong) ChartModel *dataModel;
-(void)layoutChartCanvas;
#end
#implementation ChartViewController
-(void)layoutChartCanvas {
if ([self.dataModel chartModelhasData]) {
self.view.hidden = NO;
}
}
#end
#interface LineChartViewController : ChartViewController
// pay attension here, same name but a sub class of chartModel
#property (nonatomic, strong) LineChartModel *dataModel;
-(void)drawLine;
#end
#implementation LineChartViewController
-(void)drawLine {
UIColor *color = [self.dataModel getLineColor];
[self drawLine];
NSArray *tempArray = [self.dataModel.seriesNameArray copy];
}
#end
Probably you want to say:
Can I change the class C of a property already declared in a base class in a subclass to a subclass of C?
This is the set-up
#interface PropertyClass : NSObject
#end
#interface PropertySubclass : PropertyClass
- (void)method; // Additional method
#end
#interface HolderClass : NSObject
#property PropertyClass *property; // Property is of base class
#end
#implementation HolderClass
#end
#interface HolderSubclass : HolderClass
#property PropertySubclass *property; // Property is of subclass
#end
I have no problem to access the property subclass' method in the holder's subclass:
#implementation HolderSubclass
- (void)useIt
{
[self.property method]; // No error or warning
}
#end
In addition to my comment below, I suspect that something like this happens:
// Create a subclass' object
HolderSubclass *object1 = [HolderSubclass new];
…
// Refer this object from a reference that is typed to HolderClass
// **This applies to all usages of self inside #implementation HolderClass**
HolderClass *object2 = object1; // Of course more complex
id value = [object2 method]; // Error
This error is correct. If this is the error, it is solvable. But first we have to clarify that.
BTW: This has nothing to do with better OOP. First of all this is a problem of class based programming languages, not of object orientated programming languages. Second I cannot see that this set-up will break a rule of class based or object orientated programming, esp. it fulfills Liskov's rule.
http://en.wikipedia.org/wiki/Liskov_substitution_principle
One thing you could do is declare a LineChartModel variable and not property and #synthesize dataModel to that ivar:
#interface LineChartViewController: ChartViewController {
LineChartModel *_lineChartModel;
}
-(void)drawLine;
#end
#implementation LineChartViewController
synthesize dataModel = _lineChartModel;
....
So from the outside it looks like you have a ChartModel, but inside the class you have LineChartModel. You will have to apply changes to _lineCharModel directly inside your class.
HOWEVER this is NOT my definition of better OOP!!! There's clearly a fault with the design if you need to cast your variables in subclass.
Another option I discovered after pasting this code into the editor is just use self.variable (which by the way, you should've already been doing).
#interface ChartModel : NSObject
- (BOOL)chartModelhasData;
#end
#interface LineChartModel : ChartModel
- (UIColor *)getLineColor;
#end
#interface ChartViewController: UIViewController
#property (nonatomic, strong) ChartModel *dataModel;
- (void)layoutChartCanvas;
#end
#implementation ChartViewController
- (void)layoutChartCanvas {
if ([self.dataModel chartModelhasData]) {
self.view.hidden = NO;
}
}
#end
#interface LineChartViewController : ChartViewController
// pay attension here, same name but a sub class of chartModel
#property (nonatomic, strong) LineChartModel *dataModel;
- (void)drawLine;
#end
#implementation LineChartViewController
- (void)drawLine {
UIColor *color = [self.dataModel getLineColor];
[self drawLine];
}
#end

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.

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

Reference properteries declared in a protocol and implemented in the anonymous category?

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.