Delegate twice within 2 class or call each other function in 2 class - objective-c

Basically, I want to call function from one class to another.I know I need to do delegate.
However, for example, there is class A and B. I need to call function in class A from class B and I also need to call function in class B from class A.
As a result, I need to import like
import "classA.h" //to do in class B
import "classB.h" //to do in class A
//then i may have delegate like this in both class
#protocol emailingroupViewControllerDelegate <NSObject>
-(void)updateGroupEmail :(NSString *)inputKey;
#end
The problem is that it didn't allow me to import like this in between two class. How should I do?

You have a dependency cycle in your headers. It's easy to work around; instead of including the other class' header file in each header, you use the #class directive and include the header file in the implementation file.
In classA.h, do this:
#class ClassB
#interface ClassA
...
#end
In classA.m, do this:
#import "classA.h"
#import "classB.h"
#implementation ClassA : NSObject
...
#end
In classB.h, do this:
#class ClassA
#interface ClassB
...
#end
Finally, in classB.m, do this:
#import "classB.h"
#import "classA.h"
#implementation ClassB : NSObject
...
#end
However, if you're trying to use the delegate pattern, your delegate should implement a protocol rather than be an explicit class. You should set up the connection between the delegate and the object that uses it in a third class. This would be the header for ClassA:
#protocol SomeDelegate <NSObject>
- (void)classA:(ClassA *)classA didSomethingWithAString:(NSString *)string;
#end
#interface ClassA : NSObject
#property (weak, nonatomic) id <SomeDelegate> delegate;
#end
However, again, if what you're trying to do is just have ClassA call a function in ClassB, which can call a function in ClassA, you might want to re-examine the way you've designed your classes.

Related

Duplicate protocol definition warning

First, I have seen this question as well as this, but my problem is not addressed there.
I have a protocol ProtocolA defined in its own header file. Then I have two classes ClassA and ClassB which both conform to this protocol so the protocol-header is imported in their header files.
Now it gets a bit complicated. ClassA is used (and thus imported) in a third ClassC. This class conforms to a second protocol ProtocolB. This protocol also has its own header file where it uses and imports ClassB. So my ClassC imports (either directly or indirectly) both ClassA and ClassB (which both import ProtocolA). This gives me the following warning regarding ProtocolA:
warning: duplicate protocol definition of '…' is ignored
Why is this happening? It was my understanding that the #import macro was invented exactly for avoiding this kind of problems which we had with #include. How can I solve the issue without using an include guard? I can't really remove any of the imports.
EDIT: here is the code to illustrate the situation:
ProtocolA.h
#protocol ProtocolA <NSObject>
- (void)someMethod;
#end
ClassA.h
#import "ProtocolA.h"
#interface ClassA : NSObject <ProtocolA>
...
#end
ClassB.h
#import "ProtocolA.h"
#interface ClassB : NSObject <ProtocolA>
typedef enum Type {
TypeB1,
TypeB2
} TypeB;
...
#end
ProtocolB.h
#import "ClassB.h"
#protocol ProtocolB <NSObject>
- (TypeB)someMethod;
#end
ClassC.h
#import "ProtocolB.h"
#interface ClassC : NSObject <ProtocolB>
...
#end
ClassC.m
#import "ClassC.h"
#import "ClassA.h" // the warning appears here
#implementation ClassC
...
#end
do not Import ClassB in ProtocolB header, just use #class ClassB; in it and remove #import "ClassB"

Can I hide my superclass from the users of my class?

Is it possible to encapsulate the fact that my class is derived from a certain superclass? Something like:
#class NoneOfYourBusiness;
#interface MyClass : NoneOfYourBusiness
#end
The compiler doesn’t like this: Attempting to use the forward class 'NoneOfYourBusiness' as superclass of 'MyClass'.
You could add some indirection; a dummy superclass in the inheritance tree, between MyClass and RealSuperclass:
Private header, HiddenSuperclass.h, with corresponding implementation file
#import <Foundation/Foundation.h>
#interface HiddenSuper : NSObject
- (void)makePancakes;
#end
Header for dummy class, corresponding empty implementation
#import <Foundation/Foundation.h>
#import "HiddenSuper.h"
#interface DummySuper : HiddenSuper
// Nothing to see here, folks!
#end
Then your public class's header:
#import "DummySuper.h"
#interface PublicSubclass : DummySuper
- (void)fixBreakfast;
#end
And the implementation, hidden by compilation:
#import "PublicSubclass.h"
#import "HiddenSuper.h"
#implementation PublicSubclass
- (void)fixBreakfast
{
[self makePancakes];
}
#end
Two answers
The requirement makes no sense. Client code can see the super class does not mean anything because it should be empty.
i.e. Thats all they can see
#interface NoneOfYourBusiness : NSObject
#end
#interface MyClass : NoneOfYourBusiness
- (void)publicMethod;
#end
because you should put all private / internal method / variable in private header / implementation file.
Ok you really need to hide it for some reason, then hide everything
public header
#interface MyClass : NSObject
- (void)publicMethod;
#end
private header / implementation file
#interface NoneOfYourBusiness : NSObject
#end
#interface MyClassImpl : NoneOfYourBusiness
- (void)publicMethod;
#end
#interface MyClass ()
#property (strong) MyClassImpl *impl;
#end
#implementation
- (id)forwardingTargetForSelector:(SEL)aSelector
{
return self.impl;
}
#end
you can even make MyClass inherited from NSProxy to make it a real proxy object

Move Delegates to their own classes?

My view controller is getting a little large for me. I'm implementing five delegate protocols and was about to add a sixth.
ABCViewController : UITableViewController<NSFetchedResultsControllerDelegate,
UITableViewDelegate,
UITableViewDataSource,
UIAlertViewDelegate,
CLLocationManagerDelegate>
One controller to implement them all seems ridiculous, but they aren't being used anywhere else. Should these be in their own classes or in the view controller?
You could add categories to ABCViewController, like this:
1. Move any declarations in ABCViewController.m into a private category in ABCViewController.h
// in ABCViewController.h
#interface ABCViewController : UIViewController <delegates>
// anything that's in the _public_ interface of this class.
#end
#interface ABCViewController ()
// anything that's _private_ to this class. Anything you had defined in the .m previously
#end
2. ABCViewController.m should include that .h.
3. Then in ABCViewController+SomeDelegate.h and .m
// in ABCViewController+SomeDelegate.h
#interface ABCViewController (SomeDelegateMethods)
#end
// in ABCViewController+SomeDelegate.m
#import "ABCViewController+SomeDelegate.h"
#import "ABCViewController.h" // here's how will get access to the private implementation, like the _fetchedResultsController
#implementation ABCViewController (SomeDelegateMethods)
// yada yada
#end
You can also declare conformity to that protocol in the .m file like this:
#interface ABCViewController (NSFetchedResultsControllerDelegateMethods) <NSFetchedResultsControllerDelegate>
#end
#implementation ABCViewController (NSFetchedResultsControllerDelegateMethods)
...
#end
This won't make your file shorter but at least it will be clearly divided into parts
If you are using Xcode you can try something like this for example:
#pragma mark - NSFetchedResultsControllerDelegateMethods
Quite handy to find your methods like in this tip: Pragma mark
Alternatively, depending on what you do the delegate methods and how structured is your code you could have another object that has only methods of the delegate protocol
#interface Delegate <NSFetchedResultsControllerDelegate> : NSObject
#end
You would have an instance of this object as an ivar in your ABCViewController.

Can i use two delegates: delegateA in classB, delegateB in classA?

i've got my code in HelloWorldLayer, i'm using a delegate to change the score number in ScoreLayer, and i would like to send a message back from ScoreLayer to HelloWorldLayer, in order to change the ui with a new image.
Is it ok to create a delegate in each class (one delegate of HelloW... in ScoreLayer, and one delegate of ScoreLayer in HelloW...) ? Something like that :
hellolayer.delegate = scoreLayer;
scoreLayer.powerUpDelegate = hellolayer;
?
#class MyClass does not work : the protocols are not being recognized.
"#import "..." : one of the protocol is not recognized, but i guess there will be a problem, as classA will import classB, which will import classA again etc.
How should i do? Here's some of the code :
//in HelloWorldLayer.h :
#import "ScoreLayer.h"
#protocol PowerUpDelegate
-(void)scalePowerUp;
#end
// HelloWorldLayer
#interface HelloWorldLayer : CCLayer <PowerUpDelegate>
{ … }
#property (nonatomic,retain) id <ScoreDelegate> delegate;
//in ScoreLayer.h :
//#class HelloWorldLayer; -->does not recognize the protocol
#import "HelloWorldLayer.h"
#protocol ScoreDelegate
//...
#end
#interface ScoreLayer : CCLayer <ScoreDelegate>{
//...
}
#property (nonatomic,retain) id <PowerUpDelegate> powerUpDelegate;//-->cannot find protocol definition...
Thanks
I recommend using a third class which implements both protocols and use that class to handle the delegate methods.
Yes; you can pre-declare the protocols like you pre-declare classes, so put this at the top of your ScoreLayer class:
#protocol PowerUpDelegate;

Is it possible to declare a second #interface for a category?

I am trying to declare a private #interface for a category, in the .m file.
For a normal class I would do:
#interface ClassA ()
#end
#implementation ClassA
#end
and it would work smoothly.
For a class with categories I tried:
#interface ClassA (CategoryA) ()
#end
#implementation ClassA (CategoryA)
#end
but it is giving all sort of different errors. I am trying to "extend" a category, the way that a class is extended via this syntax #interface ClassA ().
I want to have private methods for the category, and I wanted to know if, IN ADDITION to the exposed interface I am allowed to put a second category #interface in the .m file, which does not expose instance variables and methods outside the class itself.
Something like this:
ClassA+categoryA.h
#interface ClassA (CategoryA)
<some public methods>
#end
ClassA+categoryA.m file
#interface ClassA (CategoryA)
<some private methods>
#end
#implementation ClassA (CategoryA)
<here I want to be able to call the private methods above>
#end
Right now this is giving me a warning in Xcode:
Duplicate definition of category 'CategoryA' on interface 'ClassA'
Is there any way to get this behavior?
No, you can't declare two interfaces for a single category. You can do one of two things:
Englebert+Humperdinck.h
#import "Englebert.h"
#interface Englebert (Humperdinck)
- (void) croon;
#end
You can declare another category with a different name to contain the private methods. These can then be used in the same file where the private category interface is declared:
Englebert+Humperdinck.m
#import "Englebert+Humperdinck.h"
#interface Englebert (HumperdinckPrivate)
- (void) warmUp;
#end
#implementation Englebert (HumperdinckPrivate)
- (void)warmUp {
NSLog(#"Warm up");
}
#end
#implementation Englebert (Humperdinck)
- (void)croon {
[self warmUp];
NSLog(#"Croon");
// etc.
}
#end
The other option is to simply not declare the private methods. If you just define them in the implementation block, you can use them at any point in that file after they are defined (and for the latest version of Xcode/LLVM, the order is in fact unimportant -- undeclared methods can be used anywhere in the file in which they are defined). No other files will be able to see these methods.
Englebert+Humperdinck.m
#import "Englebert+Humperdinck.h"
#implementation Englebert (Humperdinck)
/* Undeclared private method */
- (void)warmUp {
NSLog(#"Warm up");
}
- (void)croon {
[self warmUp];
NSLog(#"Croon");
// etc.
}
#end
Do
#interface ClassA (CategoryA)
#end
#implementation ClassA (CategoryA)
#end
Instead. Categories can't have instance varibles. And what kind of errors are you talking about?
#interface ClassA () is an anonymous category, and you can use these as interfaces and define the implementation in the ClassA implementation as well. #interface ClassA (CategoryA) () is a syntax error and should read #interface ClassA (CategoryA)
EDIT:
To create private methods for a class, in that class' .m file you would have:
#interface ClassA ()
// Private functions declared
#end
#implementation ClassA
// Private functions defined
// Other functions defined
#end
The same can be done for named categories, however you will need to define the implementation separately to avoid warnings. Again, in the .m file:
#interface ClassA (hidden)
// Private functions declared
#end
#implementation ClassA (hidden)
// Private functions declared
#end
#implementation ClassA
// Other functions defined
#end