I made a class that uses the delegate pattern and I put it in a static library. Then, I created a demo app to test the library. The demo just has a single view controller, and in the .h file, I have this:
#interface ViewController : UIViewController <AuthenticationDelegate>
#property (nonatomic, retain) IBOutlet UITextField *usernameTextField;
#property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
#end
When I compile, I get an error right on the first line of the file that says:
Cannot find protocol declaration for 'AuthenticationDelegate'.
But, in the .m file for the same view controller, I have:
#import "Authentication.h"
#import "ViewController.h"
The file "Authentication.h" is the only header file in my static library, and it does declare the delegate class:
#class AuthenticationProvider;
#protocol AuthenticationDelegate <NSObject>
#optional
- (void)provider:(AuthenticationProvider *)provider didReplyWithResponse:(AuthenticationProviderResponse)response;
#end
Where am I going wrong?
Update:
If I put #import "Authentication.h in ViewController.h, I get this:
Undefined symbols for architecture i386:
"_OBJC_CLASS_$_AuthenticationProvider", referenced from:
objc-class-ref in ViewController.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I get that when I remove #import "Authentication.h from ViewController.m also.
Try #import "Authentication.h" in your classes .h file, not your .m file
Related
There are many questions about accessing 'private' (I hear technically there is no such thing as a private method in Obj-C) messages in Obj-C. And there are many questions addressing No visible #interface for SomeClass declares the the selector 'SomeMethod'. However, there is not one that addressed both.
So here is some code.
Example.h
#import <Cocoa/Cocoa.h>
#interface Example : NSView
#end
Example.mm
#import "Example.h"
#interface Example()
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord;
#end
#implementation Example
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord{
NSLog(#"The two words are %# %#", firstWorld, secondWord);
}
#end
ViewController.h
#import <Cocoa/Cocoa.h>
#import "Example.h"
#interface ViewController : NSViewController{
IBOutlet Example *example;
}
#end
The IBOutlet has been connected in storyboard.
ViewController.mm
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[example printWordOne:#"Hello" wordTwo: #"World"];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
// Update the view, if already loaded.
}
#end
The issue I am having is with this method call.
[example printWordOne:#"Hello" wordTwo: #"World"];
The error is No visible #interface for 'Example' declares the selector 'printWordOne:wordTwo'
I need a way to call that function without declaring it in the Example.h file. If I #import Example.mm in my ViewController.mm file I get the following:
duplicate symbol _OBJC_CLASS_$_Example in:
/path/Example.o
/path/ViewController.o
duplicate symbol _OBJC_METACLASS_$_Example in:
/path/Example.o
/path/ViewController.o
ld: 2 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I know using class_copyMethodList I can get the method list and list that method from ViewController.mm. But again is there anyway to execute the method.
Any help would be greatly appreciated.
You can simply declare category to Example class with private method declaration inside your ViewController.mm:
#import "ViewController.h"
#interface Example()
- (void) printWordOne:(NSString*) firstWorld wordTwo:(NSString*) secondWord;
#end
#implementation ViewController
// ...
#end
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.
I am stuck with this problem. I have the following .h file:
#import <UIKit/UIKit.h>
#protocol MapSettingsViewDelegate
- (void)settingsDidUpdate:(BOOL)scheme;
#end
#interface MapSettingsViewController : UIViewController
#property (nonatomic, assign) id <MapSettingsViewDelegate> delegate;
#property (nonatomic, strong) IBOutlet UINavigationBar *navBar;
#property (nonatomic, strong) IBOutlet UINavigationItem *titleItem;
#property (nonatomic, strong) IBOutlet UITableView *TableView;
- (id)init;
- (IBAction)saveAction:(id)sender;
#end
When I declare the following:
#interface MapViewController : UIViewController <MapSettingsViewDelegate>
The compiler complains with the following message:
Cannot find protocol declaration for 'MapSettingsViewDelegate'
I have the same kind of delegate declaration in other files in the same project that are compiled without a glitch. I spent the last four hours trying to figuring out what I am doing wrong. Cleaning the project does not nothing.
Problem solved. As suggested in this answer, I created a new class with a different name and copied all coded from the previous class. Worked flawlessly. It seems XCode lost track of something.
You are running into preprocessor problems. Both of your classes import each other. I think you can solve this by adding #class below your protocol declaration as shown below; and moving your #import "mapViewController.h" line into MapSettingsViewController.m file. The #class tells the compiler that you will include the class content somewhere else (in the .m file).
Note that, on the top of your MapViewController.h class file you can include #import "MapSettingsViewController.h" just like normal. Hope this help. I ran into the same problem myself earlier.
#import <UIKit/UIKit.h>
#protocol MapSettingsViewDelegate
- (void)settingsDidUpdate:(BOOL)scheme;
#end
#class MapViewController
#interface MapSettingsViewController : UIViewController
#property (nonatomic, assign) id <MapSettingsViewDelegate> delegate;
...
...
Import the MapSettingsViewController.h file
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
In my Cocoa Application I have created a Custom View Class (subclass of NSView), named "DragAndDropView". Its .h and .m files are placed in the same folder than the AppDelegate.h.
Into the AppDelegate.h, I need to declare an outlet of my DragAndDropView. It looks like this:
#import <Cocoa/Cocoa.h>
#import <DragAndDropView.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
#private
NSWindow *window;
DragAndDropView *dragAndDropView;
// Files
NSFileManager *fileMgr;
}
// Outlets
#property (assign) IBOutlet NSWindow *window;
#property (assign) IBOutlet DragAndDropView *dragAndDropView;
#end
With the import of my class (#import ), I become the following error:
'DragAndDropView.h' file not found
Anyone knows how can I fix it?
You need to use quotes instead of angled brackets in your import line. i.e. this:
#import "DragAndDropView.h"
instead of this:
#import <DragAndDropView.h>
In essence, the former is for importing headers from your project, the latter is for importing headers from system libraries.