Error when declaring delegate property - objective-c

This should be an easy question - but I'm having a hard time figuring it out. I'm trying to create a property on an object so that during prepareForSegue I can tell the object what it's delegate is. I know I could do this with protocols but I figured for this case a direct approach would be simplest. Unfortunately, the following code results in a compiler error:
#import <UIKit/UIKit.h>
#import "PlanningViewController.h"
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) PlanningViewController *planningDelegate;
#end
When I type the property declaration, Xcode recognizes PlanningViewController and even displays the text for me to just tab through. The compiler, though, complains with:
Unknown type name 'PlanningViewController': did you mean 'UISplitViewController'?
What am I doing wrong?
PlanningViewController.h looks like this:
#import <UIKit/UIKit.h>
#import "DepartmentViewController.h"
#interface PlanningViewController : UITableViewController
// Table cell connections
- (IBAction)addItemPressed:(id)sender;
#end

Remove this line from your PlanningViewController.h header file:
#import "DepartmentViewController.h"
You have something of a loop in your header files.
Better still, make DepartmentViewController.h look like this (there is no need to include PlanningViewController.h in your header file):
#import <UIKit/UIKit.h>
#class PlanningViewController;
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) PlanningViewController *planningDelegate;
#end

I think you've kind of missed one of the main points of the delegate patter which is to decouple you objects. The best way of declaring this delegate would be:
#import <UIKit/UIKit.h>
#protocol DepartmentViewControllerDelegate; // forward declaration of protocol
#interface DepartmentViewController : UITableViewController
#property (nonatomic, weak) id <DepartmentViewControllerDelegate> delegate;
#end
#protocol DepartmentViewControllerDelegate
- (void)departmentViewController:(DepartmentViewController *)controller
isProcessingPeople:(NSArray *)people
#end
In your department view controller, you would then write something like this:
if ([self.delegate respondsToSelector:#selector(departmentViewController:isProcessingPeople:)]) {
[self.delegate departmentViewController:self isProcessingPeople:people];
}
And in your planning view controller, you would implement this method:
- (void)departmentViewController:(DepartmentViewController *)controller
isProcessingPeople:(NSArray *)people {
// do necessary work here
}
The example here is just an example of one message you can send to the delegate. You can add whatever you need, but this makes it so there is no coupling between your controllers. The planning view controller knows everything it needs to about the department controller, but the department controller doesn't need to know anything about the planning controller.
If you want to stick with what you have currently, just recognize that it's not really the delegate pattern, and you should probably rename your property.

Related

Objective C protocol - some stupidly basic help needed, please

I'm having a problem when I try to add a second protocol. The first one is working just fine. So I created a test application to try out using two protocols (because I'm still learning how to use protocols). I do not know why I am having so much trouble understanding protocols. I've even gone through tutorials and still struggle with them.
My first issue when I tried to add the second protocol and use it I received the following error:
Assigning to ‘id’ from incompatible type ‘ *const _strong'
But, let's ignore that for now, because my test application is giving me this error for both protocols in my test app:
Cannot find protocol declaration
So, I will post the code for my test application, because I MUST understand the basics before tackling more difficult issues.
DelegateA Header
#import <Foundation/Foundation.h>
#protocol IDDelegateADelegate <NSObject>
#end
#interface IDDelegateA : NSObject
//other properties here
#property (nonatomic, assign) id<IDDelegateADelegate> delegateA;
#end
DelegateA Implementation
#import "IDDelegateA.h"
#implementation IDDelegateA
#synthesize delegateA;
//other methods and properties go here
#end
DelegateB Header
#import <Foundation/Foundation.h>
#protocol IDDelegeteBDelegate <NSObject>
#end
#interface IDDelegeteB : NSObject
//other properties here
#property (nonatomic, assign) id<IDDelegeteBDelegate> delegateB;
#end
DelegateB Implementation
#import "IDDelegeteB.h"
#implementation IDDelegeteB
#synthesize delegateB;
//other methods and properties go here
#end
The test class Header that uses these delegates
#import <Foundation/Foundation.h>
#import "IDDelegateA.h"
#import "IDDelegeteB.h"
#interface IDTestingDelegates : NSObject <IDDelegateA, IDDelegateB>
#end
Right here I receive the Cannot find protocol declaration error for both delegates. I've been searching on SO as well as going through tutorials and sample code. Best answer on SO was here. But I'm just not getting what I'm doing wrong. Can somebody please point out what I am missing here?
#interface IDTestingDelegates : NSObject <IDDelegateA, IDDelegateB>
should be
#interface IDTestingDelegates : NSObject <IDDelegateADelegate, IDDelegeteBDelegate>
You have to list the protocols in <...>, not interfaces.
#interface declares a class, while the ClassName <X> syntax expects X to be a protocol (in your declaration of IDTestingDelegates).
Not sure exactly what you were trying to achieve here.

Need little help incomplete implementation error in Objective-C

I'm getting an "incomplete implementation" error in my .m file, but I cannot figure it out how to fix it. I`ll post .h and .m files if you can give me tips on how to fix that. Thanks.
Apparently, I need to put more details, or I cannot post the question because the post contains mostly code, so this are just some dummy lines.
.h File
#import <UIKit/UIKit.h>
#interface BlogViewController : UIViewController <UIPickerViewDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
- (IBAction)selectPicturePressed:(id)sender;
- (IBAction)blogPost:(id)sender;
#property (weak, nonatomic) IBOutlet UITextView *commentTextField;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (nonatomic, strong) NSString *username;
#end
.m File
#import "BlogViewController.h"
#import <Parse/Parse.h>
#import "SWRevealViewController.h"
#import "PhotoViewController.h"
#interface BlogViewController ()
-(void)showErrorView:(NSString *)errorMsg;
#end
#implementation BlogViewController **//Incomplete Implementation**
#synthesize imageView = _imageView;
#synthesize username = _username;
#synthesize commentTextField = _commentTextField;
IBActions are just regular functions with syntactic sugar for connecting them to interface builder therefore you have to implement them in the .m file
.m file:
- (IBAction)selectPicturePressed:(id)sender {
// code here
}
- (IBAction)blogPost:(id)sender {
// and here
}
On the line that's giving you the Incomplete Implementation error, you can get more details about what you're missing.
You don't paste all your .m so it's anyone's guess what you're missing, however, your .h declares 2 methods and 3 protocols that you must implement.
Your .m file must have method bodies for these two methods:
- (IBAction)selectPicturePressed:(id)sender;
- (IBAction)blogPost:(id)sender;
Likely, you already have these in here, particularly if these were generated by Ctrl+Dragging from interface builder.
But you must also include, at a minimum, all the required methods from the protocols you declared.
UIPickerViewDelegate protocol official documentation
UINavigationControllerDelegate protocol official documentation
UIImagePickerControllerDelegate protocol official documentation.
(I'm not completely familiar with these protocols and don't know for sure that they actually have any #required methods.)
Your .m also has a private interface, which declares a method you must implement in the implementation.
-(void)showErrorView:(NSString *)errorMsg;
You declared this method in a private interface, so be sure to implement this method as well.
Regardless of what you're missing, Xcode will absolutely tell you if you just click on the error/warning. Xcode will give you the names of the methods its expecting to find in your implementation but cannot.

do you need to import .h files when using delegates?

-(IBAction)ok
{
//send message to the delegate with the new settings
[self.delegate setHeight:_height Width:_width Mines:_mines];
[self.delegate dismissViewControllerAnimated:YES completion:nil];
}
the first message to the delegate wouldn't work until i imported ViewController.h, but the second one worked without the import.
if i add -(void)setHeight:(int)h Width:(int)w Mines:(int)m; as required in the optionsViewController protocol will that mean that i no longer have to import the root .h file.
i intend to use delegation to send messages in other parts of the program so i want to make sure i am using it correctly and not importing things when i don't need to.
Thank you.
if i add -(void)setHeight:(int)h Width:(int)w Mines:(int)m; as required in the optionsViewController protocol will that mean that i no longer have to import the root .h file.
Yes! You could also add it as #optional and it would work (remember to check if the delegate -respondsToSelector: in that case). The whole idea is that your object regularly knows nothing about the delegate object - except that it conforms to the protocol (ie implements the #required and possibly the #optional methods).
Added for clarification (on my phone, which is a pain in the butt):
//OptionsViewController.h
//this object does NOT have to import
//the calling viewControllers .h file
//which is what I think the OP does
#protocol optionsViewControllerProtocol;
#interface OptionsViewController : UIViewController
#property (nonatomic, assign) id<optionsViewControllerProtocol> delegate; //should be id, could be UIViewController too, if absolutely necessary (better design to make it id)
#end
#protocol optionsViewControllerProtocol <NSObject>
#required
-(void) setHeight: (NSInteger) height;
#end
//viewController.h
#import "optionsViewController.h" //necessary to get the protocols definitions
#interface OptionsViewController: UIViewController <optionsViewControllerProtocol>
//.....
If you define your delegate property to be of class UIViewController*, then the compiler will recognize the dismissViewControllerAnimated:completion: method without you needing to import anything, since that's a standard method for that class.
For a custom method, i.e. setHeight:Width:Mines:, you absolutely need to import the header file, or have it imported somewhere up the import chain.
Example: You have MyProtocol.h, and you want SomeClass to have a delegate property that conforms to that protocol. If you #import "MyProtocol.h" in SomeClass.h, you don't need to re-import it in SomeClass.m.
// SomeClass.h
#import "MyProtocol.h"
#interface SomeClass : NSObject
#property (weak, nonatomic) id<MyProtocol> delegate;
#end
//SomeClass.m
#import "SomeClass.h"
#implementation SomeClass
- (void)someMethod
{
[self.delegate myProtocolMethod];
}
#end

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.

trouble with declaring a delegate

i have two views with view1 calling view2. i need to pass data from view2 back to view1. so i am attempting to set up a delegate. here's what i got in view controller 2:
.h file
#protocol addEventDelegate <NSObject>
-(void) setAddedEventFlag:(BOOL) hasAddedEvent;
#end
#interface AddEventViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate>
#property (weak, nonatomic) id delegate; //changed from strong to weak
i then #synthesize delegate in the .m file
when try to include the addEventDelegate for the first view controller, xcode can not find it:
.h file
#import "AddEventViewController.h"
#interface FieldReportViewController : UIViewController <UITextFieldDelegate,
UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate, addEventDelegate>
i get the error: "Cannot find protocol declaration for 'addEventDelegate'".
what is wrong?
EDIT:
//code
ERRORS:
Make sure your spelling is correct.
Make sure that AddEventViewController.h/.m are added to the project.
Other than that, what you have is fine.
Edit
Something else I would suggest is to rename your delegate, perhaps there is a naming conflict. Although I haven't seen any issues with 'add' and 'set', but I've seen issues in the past when prefixing with, say, 'new'.
Also, clean your project, and rebuild and see if that helps.
There could be a situation if you have multiple targets in your project, and possibly only added AddEventViewController.h/m to one of them, and you are building/debugging a different target.
Here's the correct way to define a protocol
#protocol addEventDelegate; // forward declaration for delegate property
#interface AddEventViewController : UIViewController <UITextFieldDelegate, UITextViewDelegate, UIPickerViewDelegate, UIPickerViewDelegate>
{
id <addEventDelegate> *delegate
}
#property (weak, nonatomic) id <addEventDelegate> *delegate;
#end // interface
#protocol addEventDelegate <NSObject>
// #optional // if you want to make it optional
-(void) setAddedEventFlag:(BOOL) hasAddedEvent;
#end // protocol
Solved the issue. i had an #import loop. I was #importing all my classes in my .h files. i changed to #Class in .h file and moved the #import's to the .m files and works like a charm now.
You can import addEventDelegate in FieldReportViewController.m file
#interface FieldReportViewController ()<AddEventDelegate>
#end
This one is working in my app