i've worked with delegation before. i know how to create delegation from a superview to a subview class. however, i'm trying to do it the opposite way using the same approach but it's not working! is delegation meant only to work one way or is there a way/trick to use it as a two way communication between the classes? I'm receiving an error at the parent/superview .h class which is:
Cannot find protocol definition for 'SubViewControllerDelegate'
my code goes like this:
subview.h
#import <UIKit/UIKit.h>
#import "SuperViewController.h"
#protocol SubViewControllerDelegate <NSObject>
- (void)someMethod:(NSData *)data;
#end
#interface SubViewController : UIViewController
#property (weak, nonatomic) id <SubViewControllerDelegate> delegate;
#end
subview.m:
[self.delegate someMethod:data];
SuperView.h
#import <UIKit/UIKit.h>
#import "SubViewController.h"
#interface SuperViewController : UIViewController <SubViewControllerDelegate>
#end
SuperView.m:
#pragma mark - SubView Controller Delegate Methods
- (void)someMethod:(NSData *)data{
NSLog(#"%#", data);
}
am i doing anything wrong or missing out anything?
You have an "import-cycle", because "SuperViewController.h" imports "SubViewController.h" and vice versa.
Removing the #import "SuperViewController.h" in "SubViewController.h"
should solve the problem.
If you really need that class to be declared in "SubViewController.h", use
#class SuperViewController; to avoid the import-cycle.
Remark: The <SubViewControllerDelegate> protocol declaration is probably not
needed in the public interface "SuperViewController.h" at all.
In "SuperViewController.h", declare the class as
#interface SuperViewController : UIViewController
In "SuperViewController.m", define a class extension with the protocol:
#interface SuperViewController () <SubViewControllerDelegate>
#end
Related
How to implement Child's delegates in Parent?
Parent.h:
#interface Parent : NSObject
Child.h
#import "Parent.h"
#protocol ChildDelegate <NSObject>
- (void)someMethod;
#end
#interface Child : Parent
I cannot declare Parent's interface to be:
#interface Parent : NSObject<ChildDelegate>
since it need to import "Child.h" and it will be circular import.
How can i solve this?
You should declare protocol conformance in source files (with .m extension).
You can declare Parent class in Parent.h without conformance to ChildDelegate protocol.
#interface Parent : NSObject
And in your Parent.m file you can write something as following.
#import "Child.h"
#interface Parent() <ChildDelegate>
#end
#implementation Parent
// Your implementation code here
#end
I just got started working with delegates.
from some reason I cannot do it, and I see errors.
I tried to do the next code on a new project and it was OK, but when i'm moving this code to my main project I have a few issues.
my NSObject class .h:
#protocol myNSObjectClassDelegate <NSObject>
#required
-(void)doSomething;
#end
#interface GeneralMethods : NSObject
#property (nonatomic,strong) id<myNSObjectClassDelegate> delegate;
#end
my NSObject class .m:
#synthesize delegate;
-(void)SomeMethod {
if ([delegate respondsToSelector:#selector(doSomething)]) {
[delegate doSomething];
}
}
my UIViewController .h
#import "GeneralMethods.h"
#interface view : UIViewController<UIGestureRecognizerDelegate,
UINavigationControllerDelegate,
UIImagePickerControllerDelegate,
myNSObjectClassDelegate>
The error is here at .h - Cannot find protocol declaration for 'myNSObjectClassDelegate'
my UIViewController .m
-(void)doSomething{
}
What am I doing wrong?
EDIT : I figure it out:
For some reason, at my NSObject class, if I'm moving the #import myUIViewcontroller after this:
#protocol myNSObjectClassDelegate <NSObject>
#required
-(void)doSomething;
#end
the problem solved.
We can't see all the code but after reading some more of the exchanges it looks like dependencies are maybe added out of order. I recommend moving the protocol into its own file and #import'ing it to all the places that use it. This way you definitely will be importing things in the order you expect.
In addition to that, the following property declaration:
#property (nonatomic,strong) id<myNSObjectClassDelegate> delegate;
Delegates should be declared as weak, not strong.
#property (nonatomic,weak) id<myNSObjectClassDelegate> delegate;
The reason is to avoid retain cycles/memory leaks. Typically, though not always the relationship looks like this:
Parent Object (usually Controller) -----STRONG-----> Child (View often)
View Thing ----WEAK--------> delegate (actually the Parent Object)
Now if the relationship is STRONG both ways, releasing the parent from all who own it will not be sufficient to release it since its child also holds an owning relationship to it.
Also you can omit the:
#synthesize delegate;
Auto property synthesis renders this obsolete.
Make sure to import your NSObject class .h. file into your UIViewController's .h file (or wherever you declare the protocol). As it stands, you haven't imported the header that declares the protocol so your view controller has no way of knowing that it exists.
Ex:
#import "FileWithProtocol.h"
#interface MyClass <MyProtocol>
...
#end
In the view controller .h file, try adding this line:
#protocol MyNSObjectClassDelegate;
before
#interface ...
I have searched for related questions, but nothing has worked for me so I will describe my problem. I have two classes. Lets call them ClassA and RootViewController. RootViewController has a button that will trigger an action and delegate it to ClassA. The header for RootController looks like this:
#import <UIKit/UIKit.h>
#protocol RootViewControllerDelegate;
#interface RootViewController : UIViewController <UIPageViewControllerDataSource> {
}
...
#end
#protocol RootViewControllerDelegate <NSObject>
-(void)buttonPressed : (UIButton *) button;
#end
The ClassA header looks like this:
#import "RootViewController.h"
#interface RightPanelViewController : UIViewController <RootViewController>
...
#end
And I get the error :"Cannot find the protocol declaration for 'RootViewController'. Like I said, I have read some questions related to the same topic, the documentation for delegates, but I'm not able to see what the problem is. I would appreciate some help on this matter.
Change your interface line to
#interface RightPanelViewController : UIViewController <RootViewControllerDelegate>
ie. the name in angle brackets must match exactly with the name in your #protocol definition.
I have following header:
#protocol AttachmentsViewDelegate <NSObject>
#required
- (void)spaceRequestedWithSize:(CGSize)size sender:(AttachmentsView*)sender;
#end
#interface AttachmentsView : UIView
#property id<AttachmentsViewDelegate> delegate;
#property NSArray *attachments;
- (void)takePicture;
- (void)deletePictures;
#end
Doesn't work because inside #protocol I reference to AttachmentsView and it's not declared yet.
If I move #protocol below #interface - I have another problem, because delegate property doesn't know about #protocol.
I know I can use id, UIView for types, but to keep it "strongly typed", what can I do? I really prefer not to break it down into 2 files. Any other options/suggestions?
Use #class to forward-declare AttachmentsView like so:
#class AttachmentsView;
#protocol AttachmentsViewDelegate <NSObject>
// Protocol method declarations...
#end
Alternatively, use #protocol to forward-declare the protocol:
#protocol AttachementsViewDelegate
#interface AttachmentsView : UIView
// Ivar, method, and property declarations...
#property id<AttachmentsViewDelegate> delegate;
#end
just write:
#class AttachmentsView;
on top of the file.
In case you wish to declare the class first, and then the protocol, write first:
#protocol AttachmentsViewDelegate;
on top of the file.
#import "MPOContactAuthorizationManager.h"
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
MPOContactAuthorizationManager and ContactState are not resolving to types even though they are declared in MPOContactAuthorizationManager:
#import "MPOContactAuthorizationManagerDelegate.h"
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Any ideas as to why these are not resolving? Both are getting the error "Expected a type"
Thanks
Mike
You have a circular dependency. Update the MPOContactAuthorizationManagerDelegate.h header by getting rid of the #import line and adding the following:
#class MPOContactAuthorizationManager;
just before the #protocol line.
Just put both in one .h file (you still need the forward declaration for MPOContactAuthorizationManager):
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#class MPOContactAuthorizationManager;
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
Replace the import of "MPOContactAuthorizationManagerDelegate.h" from MPContactAuthorizationManager.h by using a forward declaration of the protocol:
#protocol MPOContactAuthorizationManagerDelegate;
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
........
You need to choose this import scheme as you are referring to a user defined type (the ContactsState type) in the protocol's header - so this header needs to import the manager's header. In the manager's header, however, you only refer to the protocol as the types of the method parameters, so you can legally forward-declare here.
In general, you should only import one header from another in a few cases:
Declaring a class in your header that's a subclass of a class defined in the other header
Referring to user defined types (e.g. via a typedef) in your header that are defined in the other header
Declaring a class in your header as conforming to a protocol declared in another header
Declaring a category in your header for a class defined in another header
I think I'm forgetting one, so saving this space for that one.
Also - read this enlightening answer.
The more common case of needing protocol and class names in public method parameters and properties can be accomplished using forward declarations with #class and #protocol. Although, if it were me, I'd keep the protocol declaration in the same header as the authorization manager - seems more convenient that way. Note that you will need to do a forward-declaration within the file for this. For example:
typedef enum _contactsState {
kContactsStateUnknown,
kContactsStateAllowed,
kContactsStateDisallowed
} ContactsState;
//forward-declare the protocol before referencing it in the file
#protocol MPOContactAuthorizationManager;
#interface MPOContactAuthorizationManager : NSObject <UIAlertViewDelegate> {
ContactsState _contactsAuthorizationState;;
}
#property (strong, nonatomic) NSObject<MPOContactAuthorizationManagerDelegate> *delegate;
#property (nonatomic) ContactsState contactsAuthorizationState;
........
#end
// Provide the real protocol declaration.
#protocol MPOContactAuthorizationManagerDelegate <NSObject>
- (void)authorizationManger:(MPOContactAuthorizationManager *)manager
didUpdateContactState:(ContactsState)contactState;
#end