Objective C protocol - some stupidly basic help needed, please - objective-c

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.

Related

Cannot find interface declaration for superclass of

I know this is a common subject but I did not find any answer to help me out with this problem.
Well, I do have (by now) 3 .h files,
One is the superclass of the two others.
Superclass : ExportationAutoFilterNew
#import <Foundation/Foundation.h>
#import <HIDDEN/PluginFilter.h>
#class MyOutlineView;
#interface ExportationAutoFilterNew : PluginFilter
#property (assign, nonatomic) NSUserDefaults *prefs;
#property (assign, nonatomic) MyOutlineView *databaseOutline;
#end
Then, sub-classes : DetectNewExams & ExportExams
#import <Foundation/Foundation.h>
#import <HIDDEN/PluginFilter.h>
#import "ExportationAutoFilterNew.h"
#interface DetectNewExams : ExportationAutoFilterNew
- (void)detectExams:(NSDate*)currentDate timeInterval:(double)timeInterval afterExitHidden:(BOOL)check;
And
#import <Foundation/Foundation.h>
#import <HIDDEN/PluginFilter.h>
#import "ExportationAutoFilterNew.h"
#interface ExportExams : ExportationAutoFilterNew
- (void)exportExams:(NSManagedObject*)curObj;
The .m goes like this
Superclass : ExportationAutoFilter
#import <HIDDEN/PreferencesWindowController.h>
#import <HIDDEN/browserController.h>
#import "ExportationAutoFilterNew.h"
#import "DetectNewExams.h"
#implementation ExportationAutoFilterNew
Xcode for this file (ExportationAutoFilterNew.m) :
Instance method '-detectExams:timeInterval:afterExitHidden:' not found (return type defaults to 'id')
For the call of :
[self detectExams:lastExportDate timeInterval:0 afterExitHidden:YES];
Sub-classes : DetectNewExams
#import <HIDDEN/PreferencesWindowController.h>
#import <HIDDEN/browserController.h>
#import "DetectNewExams.h"
#import "ExportExams.h"
#implementation DetectNewExams
In this file (DetectNewExams.m), Xcode says :
Instance method '-exportExams:' not found(return type defaults to 'id')
Calling :
[self exportExams:curObj];
And then : ExportExams
#import <HIDDEN/PreferencesWindowController.h>
#import <HIDDEN/browserController.h>
#import "ExportExams.h"
#implementation ExportExams
I'm wasting hours on this thing and I can't figure the problem out, may you help me ? I looked up for compiling circle but I don't think I created one with my imports ..
Thanks.
Your interface is not properly declared. Try this.
#interface ExportationAutoFilterNew : PluginFilter
#property (nonatomic) NSUserDefaults *prefs;
#property (nonatomic) MyOutlineView *databaseOutline;
#end
Now that you have posted the actual error, this becomes more clear. But you still haven't posted enough context.
Instance method '-detectExams:timeInterval:afterExitHidden:' not found (return type defaults to 'id')
That means that the method declaration hasn't been seen at the time the code was compiled or the method is declared on some class that whatever was being called is not an instance of.
Since you haven't shown the call site or the declaration of the variable being called, this is a guess. The method is declared on the DetectNewExams class. I'd bet you have a variable that points to an instance of ExportationAutoFilterNew and, therefore, the compiler is correctly warning that the method doesn't exist on the class.

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.

Using #class to get access to a delegate protocol declaration

I've read that you should try to use #class in your header file instead of #import but this doesn't work when your #class contains a delegate protocol that you're trying to use.
MyView.h
#import <UIKit/UIKit.h>
#class MyCustomClass; // <-- doesn't work for MyCustomClassDelegate, used below
#interface MyView : UIView <MyCustomClassDelegate>
#end
I think I'm overlooking something, is there a way to get #class to work in this situation or is #import my only choice?
Edit: One work around for this is, of course, declaring your #import MyCustomClass and MyCustomClassDelegate in the private interface section of the .m file instead of the .h file.
you can use #protocol to forward declare a protocol if you only need it for variables such as this:
#protocol MyProtocol;
#interface MyClass {
id<MyProtocol> var;
}
#end
In your case the declared class is trying to conform to a protocol so the compiler must know about the protocol methods at this point in order to deduce weather or not the class conforms.
In this case, I think your options are to split the protocol into its own file and #import that header, or declare the protocol in that header above the class declaration that uses it.
You can only forward-declare a protocol in the same header file for usage in method return values or parameter types. In your case you want the class to conform to the protocol, so it won't work since it defines behavior that will be added to the class itself (i.e. the methods it will respond to).
Therefore, you must #import the protocol. For this reason, it is probably a good idea to split the protocol and class up into separate files. See this answer for more information.
MyCustomClassDelegate is a protocol, not a class. Telling the compiler about the existence of MyCustomClass tells it nothing about the existence of the protocol.
You will need to declare your delegate protocol before the class:
MyCustomClass.h:
#import <UIKit/UIKit.h>
#class MyCustomClass;
#protocol MyCustomClassDelegate <NSObject>
- (void)myCustomClass:(MyCustomClass *)customClass
didBlah:(BOOL)blah;
#end
#interface MyCustomClass : NSObject <MyCustomClassDelegate>
#end
And you cannot even use #protocol to forward-declare the delegate protocol; the compiler must see the complete declaration, therefore change your #class for an #import:
MyView.h:
#import <UIKit/UIKit.h>
#import "MyCustomClass.h" // the compile now knows what MyCustomClassDelegate is
#interface MyView : UIView <MyCustomClassDelegate>
#end
You cannot forward declare a protocol you conform to.
If you are using MyView as a MyCustomClassDelegate only in MyView's implementation, you can use Extension in MyView's .m file, such as this:
#import "MyView.h"
#import "MyCustomClassDelegate.h"
#interface MyView () <MyCustomClassDelegate> {
}
#end
#implementation MyView
...
#end

Error in protocol declaration

I am getting an error as:
protocol declaration not found
I couldn't find out what's the reason. Now I am using ARC. I doubt that the issue is due to that. Here is the code I am using for protocol declaration
//This is the first page we are declaring the Delegate
.h
#protocol ImageDelegate
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
#interface GetAddedMovieList : UIViewController<UITableViewDataSource,UITableViewDelegate>{
id<ImageDelegate> delegate;
}
#property(nonatomic, strong)id<ImageDelegate> delegate;
#end
.m
#synthesize delegate;
//This is page in which i tried to set delegate. Here I am getting the error.
#interface ImageEnlarge : UIViewController<ImageDelegate>{
IBOutlet UIImageView *imgEnlarge;
NSString *stgImageName;
}
I see several (possible) issues in your code.
#property(nonatomic, strong)id<ImageDelegate> delegate;
delegates should be weak. GetAddedMovieList do now own the delegate by any mean and therefore shouldn't have an impact on its life cycle.
#synthesize delegate = delegate;
By default #synth uses either ivar_ or _ivar lately. With the latest LLVM #synth aren't necessary anymore btw, neither ivars.
#synthesize outside an #implementation ?
Have you checked your #imports?
It's probably an import loop. Do you #import the correct file for where you are using the protocol? And are you importing that file in the protocol file? If so then you have an import loop. Use forward declaration in the protocol's header instead and that should solve it. (#class)
You are putting an #interface on a .m file, are you trying to create a private #interface? With an IBOutlet declared there?
After seeing your edit, I am guessing there is only missing an import on the .h of your ImageEnlarge class.
Try like it.
#protocol ImageDelegate<NSObject>
#optional
-(void)ImageSelected:(UIImage *)ImageName;
#end
And also add this property.
#property(nonatomic,assign)id<ImageDelegate> delegate;
I think it will be helpful to you.

Xcode warns about missing protocol definition, even though #protocol is used

Since I had a import-cycle recently, I'm moving all #import statements (concerning my own files) from the header into the corresponding .m-file. I also added #class and #protocol forward-declarations to soothe the compiler. However, I still get he following warning:
Cannot find the protocol definition for 'MyCustomDelegate'.
As I said, there is an #protocol MyCustomDelegate before I use it in the #interface-Block. Interestingly this warning only occurs if the corresponding delegate is declared in another file (whose header is imported in the .m-file).
I read that one solution is to declare the delegate in a separate header file and import that file directly in the header of the class that implements the delegate. Is this really the way to go? Are there any other solutions? I think those delegates already bloated our code enough, now I should go on and even declare an own file for it?
Small sample code to better illustrate the problem:
NewFooController.h
#import <UIKit/UIKit.h>
#protocol NewFooControllerDelegate;
#interface NewFooController : UITableViewController
#property (nonatomic, weak) id<NewFooControllerDelegate> delegate;
#end
#protocol NewFooControllerDelegate
#end
HomeTableViewController.h
#import <UIKit/UIKit.h>
#protocol NewFooControllerDelegate;
// warning points to line below
#interface HomeTableViewController : UITableViewController <NewFooControllerDelegate>
#end
HomeTableViewController.m
#import "HomeTableViewController.h"
#import "NewFooController.h"
#implementation HomeTableViewController
#end
HomeTableViewController.h references the protocol, but it hasn't been declared yet.
If you import NewTaskController.h in HomeTableViewController.h before it attempts to use it, it should solve your problem.
Of course you can then remove the import from HomeTableViewController.m
Not sure if this is "best way", but try import header of class that implement protocol before class header file.
HomeTableViewController.m
#import "NewFooController.h"
#import "HomeTableViewController.h"
#implementation HomeTableViewController
#end
And you can remove protocol declaration in HomeTableViewController.h
#import <UIKit/UIKit.h>
#interface HomeTableViewController : UITableViewController <NewFooControllerDelegate>
#end