Reputation: 8108
In DataProvider.h
@protocol NewDataProviderProtocol
- (void)fetchNewData;
@end
In SomeClass
#import DataProvider.h
@interface SomeClass :NSObject <NewDataProviderProtocol>
@end
When I try to make SomeClass conform to NewDataProviderProtocol it says,
No type or protocol named 'NewDataProviderProtocol'
It's weird since I already imported header DataProvider.h in which the protocol is declared.
So I forward declare the NewDataProviderProtocol before interface of SomeClass but xcode warns
Cannot find definition for **NewDataProviderProtocol**
What's the reason and the workaround for this?
Upvotes: 2
Views: 273
Reputation: 16650
A. Reason
Likely you have a include cycle, because you import SomeClass.h into DataProvider.h, too. This leads to an undeclared identifier.
Why is it that way? Let's have an example:
// Foo.h
#import "Bar.h"
@interface Foo : NSObject
…// Do something with Bar
@end
// Bar.h
#import "Foo.h"
@interface Bar : NSObject
…// Do something with Foo
@end
If you compile, let's say Foo.h, the precompiler will expand this:
He gets …:
// Foo.h
#import "Bar.h"
@interface Foo : NSObject
…// Do something with Bar
@end
… imports Bar.h (And strips comments … But let's focus on the main topic.) …
// Foo.h
// Bar.h
#import "Foo.h"
@interface Bar : NSObject
…// Do something with Foo
@end
@interface Foo : NSObject
…// Do something with Bar
@end
Foo.h will not be imported again, because it is already imported. Finally:
// Bar.h
@interface Bar : NSObject
…// Do something with Foo
@end
@interface Foo : NSObject
…// Do something with Bar
@end
This is quite clear: If A relies on B and B relies on A, it is impossible for a serial data stream as a file is, to have A ahead of B and B ahead of A at the same time. (Files are not subjects of the theory of relativity.)
B. Solution
In most cases you should give your code a hierarchy. (For many reasons. Having no import problems is one of the least important.) I. e. in your code an import of SomeClass.h into DataProvider.h looks strange.
Having such a problem is a code smell. Try to isolate and repair the reason for that. Do not move code pieces into different location to find a pace, where it works. This is code lottery.
C. Structure
Usually you have a class that expects others to conform to a protocol. Let's have an example:
// We declare the protocol here, because the class below expects from other classes to conform to the protocol.
@protocol DataSoure
…
@end
@interface Aggregator : NSObject
- (void)addDataSource:(id<DataSource>)dataSource
// We are using a protocol, because we do not want to restrict data sources to be subclass of a specific class.
// Therefore in this .h there cannot be an import of that – likely unknown - class
@end
SomeClass, that conforms to the protocol
#import "Aggregator.h"
@interface SomeClass:NSObject<DataSource>
…
@end
Upvotes: 1
Reputation: 27050
Two things to change:
Change definition like this:
@protocol NewDataProviderProtocol <NSObject>
- (void)fetchNewData;
@end
Why? Why tack a protocol of NSObject to a protocol implementation
Import DataProvider
in SomeClass.m
only. You can always create an extension of SomeClass
inside implementation file where you can bind the protocol to conform a particular class.
@interface SomeClass ()<NewDataProviderProtocol>
@end
Why? It's the best practice. And to overcome forward class declaration errors. E.g. Objective-C: Forward Class Declaration
Upvotes: 0