NSViewController subclass troubles - objective-c

I have created a NSCollectionViewItem subclass, called TSCollectionViewController. It overrides one method, setRepresentedObject:. I plan on using it in my NSView, TSTopChartView. Oddly enough, I get an error when I add it to the TSTopChartView.h file (pictured below).
Obviously, Xcode doesn't like TSCollectionViewController for this file. I just can't figure out why! I've imported the file, so it shouldn't be an unknown type name. Any ideas? Thank you for your time!
Here is TSCollectionViewController.h:
#import <Cocoa/Cocoa.h>
#import "TSTopChartCell.h"
#import "TSPodcastEpisodeCell.h"
#import "TSDetailView.h"
#interface TSCollectionViewController : NSCollectionViewItem
#end

You have a circular #import dependency between TSCollectionViewController.h and TSTopChartView.h. In your case you can break it easily by removing #import "TSTopChartCell.h" from TSCollectionViewController.h.
If you end up in a case where you really need the class TSTopChartCell to be declared in TSCollectionViewController.h you can fix this by adding #class TSTopChartCell instead of the #import "TSTopChartCell.h". Then you can actually #import "TSTopChartCell.h" in the implementation file, TSCollectionViewController.m.

Related

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

iOS: What can cause the Xcode compiler to throw errors when I include my AppDelegate.h into another header file?

I am trying to #import my "AppDelegate.h" into another header file of the same project in order to access methods of the AppDelegate of my iOS project.
So, my header file looks something like this:
#import
#import "DataProvider.h"
#import "MyAppDelegate.h"
#interface MyViewController : UIViewController <UITextFieldDelegate, UIAlertViewDelegate> {
...
}
and I want to use my AppDelegate like this:
MyAppDelegate* appDelegate = (MyAppDelegate*)[UIApplication sharedApplication].delegate;
[appDelegate doSomething];
However, as soon as I #import "MyAppDelegate.h", the compiler throws a lot of (unrelated) errors, like
Cannot find interface declaration for 'MyOtherViewController', superclass of 'MyOtherViewController2'
The thing is: I can include my AppDelegate just fine in other headers. And I cannot figure out what the difference might be. Please help me figure out what could cause this! Thanks a lot!
PS: This happens with GCC as well as the new LLVM.
Move the #import into the .m file. If you need the MyAppDelegate symbol in your .h, use #class MyAppDelegate; instead.

#import in objective C: Am I doing this wrong?

Sorry, couldn't find a more appropriate title.
In My code I have two classes which should know of each others existence. So I use an instance variable which points to the other class. For that to work (I guess?) the other classes headers file should be imported so it knows which methods it has and such.
Here is my code (stripped down)
MainMenuController.h:
#import <Cocoa/Cocoa.h>
#import "IRCConnection.h"
#interface MainMenuController : NSViewController {
IRCConnection *ircConnection;
}
#property (strong) IRCConnection *ircConnection;
#end
IRCConnection.h:
#import <Foundation/Foundation.h>
#import "MainMenuController.h"
#interface IRCConnection : NSObject {
MainMenuController *mainMenuController;
}
#property (strong) MainMenuController *mainMenuController;
#end
As you can see they both import each other, but this creates an error (Unknown type name 'IRCConnection') in one, and in the other Unknown type name 'MainMenuController'.
However when the connection is just one way (e.g. only MainMenuController knows about IRCConnection) and thus there is only an import statement in one of the two, it works fine.
How can I have them to know about each other? In both ways.
Hope this question makes any sense.
you could remove the import from IRCConnection.h and use a #class statement instead.
like this:
#import <Foundation/Foundation.h>
#class MainMenuController;
#interface IRCConnection : NSObject {
then add a #import "MainMenuController.h" to IRCConnection.m
In the header, use forward declaration:
#class IRCConnection;
#interface MainMenuController : NSViewController {
IRCConnection *ircConnection; // ok
}
In the source file (.m), do #import.
You cannot have circular imports. You need to break them up, or introduce some forward declarations.

Cannot find protocol declaration

I have two view controllers A and B, and they both have each other as their delegates.
When I did nothing except define the protocols at the beginning of the header files and #import the other's header file, I got two errors along the lines of -
cannot find protocol declaration for "BDelegate", which was showing in
A.h (where I wrote ) cannot find protocol declaration for
"ADelegate", which was showing in B.h (where I wrote )
Looking online, people had written earlier that the circular inclusion of header files could be leading to the problems. They recommended either using #include instead, or #class declaration like -
#class A
instead of
#import A.h
inside #import B.h
I have tried almost every combination of these imports, and #classes, and #include but still can't get rid of the warnings. Also, solutions online recommended moving the #import to the .m files but that didn't help either. Part of the reason is that the solutions online are kinda fuzzy - if you could break it down that would be great.
Any suggestions about what can be done to fix this?
-- BigViewController.h --
#import "BaseViewController.h"
#include "BaseViewController.h"
#class BigViewController;
#protocol BigViewControllerDelegate
-(void) BigViewController:(BigViewController *) bigView;
#end
#interface BigViewController : UIViewController <BaseViewControllerDelegate>
{
//delegate
id <BigViewControllerDelegate> delegate;
ivars...
}
#properties...
#end
--------------------------------------------------
-- BaseViewController.h --
#<UIKit/UIKit.h>
#import "BigViewController.h"
#include "BigViewController.h"
#class BigViewController;
#protocol BaseViewControllerDelegate
- (void) setParametersWithItemChosen:(Item *) item;
#end
#interface BaseViewController : UIViewController <...BigViewControllerDelegate...>
{
ivars...
//delegate
id <BaseViewControllerDelegate> delegate;
}
#properties...
#end
Let me reduce the sample even further, and label the lines:
VC1.h
#import "VC2.h" // A
#class VC1;
#protocol VC1Delegate // B
#end
#interface VC1 : UIViewController <VC2Delegate> // C
#end
VC2.h
#import "VC1.h" // D
#class VC2;
#protocol VC2Delegate // E
#end
#interface VC2 : UIViewController <VC1Delegate> // F
#end
Consider what happens when something #imports VC1.h: It reaches line A, then the import is processed. Line D does nothing because VC1.h was already imported. Then line E is processed. Then line F, and we get an error because we haven't gotten to line B yet so the protocol is not declared!
Consider then what happens when something #imports VC2.h: It reaches line D, then the import is processed. Line A does nothing because VC2.h was already imported. Then line B is processed. Then line C, and we get an error because we haven't gotten to line E yet so the protocol is not declared!
The first step is to reconsider whether both of these classes really need to be each other's delegates. If you can break the cycle, that would probably be the way to go. If not, you'll need to restructure your headers. The most straightforward way is probably to put the delegates into their own headers:
VC1Delegate.h
#class VC1;
#protocol VC1Delegate // B
#end
VC1.h
#import "VC1Delegate.h"
#import "VC2Delegate.h"
#interface VC1 : UIViewController <VC2Delegate> // C
#end
VC2Delegate.h
#class VC2;
#protocol VC2Delegate // E
#end
VC2.h
#import "VC1Delegate.h"
#import "VC2Delegate.h"
#interface VC2 : UIViewController <VC1Delegate> // F
#end
If you trace through the imports now, you'll see that the appropriate protocols will now always be declared before the #interface lines try to use them.
Write protocol declaration code above the #import lines
e.g.
#protocol -----
#end
import ----
#interface classname ---
I had almost the same problem, and I fixed it thanks to the answer above, but in a slightly different way.
all I did was to put the #import line after the protocol declaration in the header file.
hope I can help. and if anyone know that this is bad programing for some reason, pls let me know
I found another solution to this issue because I didn't really like the idea of just having some #imports in between the class and the protocol declaration.
Basically you just move <YourProtocolName> from the .h class file to the class extension in the .m file
So in your .m file you add
#interface YourClassName () <YourProtocolName>
#end
I don't know if this is really a good practise but it looks like a cleaner solution to avoid the import cycles.
Try putting the < BaseViewControllerDelegate > or < BigViewControllerDelegate > in implementation file rather then header file. It will work.
I followed the fix of moving the protocol before the import and it fixed the problem... the import included the delegate, so that was causing the problem.
But then I thought, why was I importing the delegate anyway? I wasn't referencing its properties and I wasn't calling any of its methods directly (that's what the protocol declare was for).
I tried commenting out the import of the delegate and saw where the error came up and found that what I was importing when I was importing the delegate was actually a declaration that the delegate was importing i.e. I was importing A (also my delegate), A was importing B, what I was actually using was B. So I left the import of A commented out and added an import for B. Then I could put the import-protocol order back the way it was.

#protocol implementation in #interface in Objective-C

I need to develop an application which has a interface which implements methods of 3 protocols.
Assume protocol A extends protocol B and protocol C, and interface implements protocol A.
This is how my code looks,
// This is in MyClass.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_A"
#interface MyClass : NSObject <protocol_A>
{
}
#end
//This is MyClass.m file
#import "MyClass.h"
#implementation myClass
-(void)methodinA
{
NSLog(#"I'm in protocol_A");
}
}
-(void)methodinB
{
NSLog(#"I'm in protocol_B");
}
-(void)methodinC
{
NSLog(#"I'm in protocol_C");
}
#end
//This is protocol_A.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_B.h"
#import "protocol_C.h"
#protocol protocol_A <protocol_B, protocol_C>
-(void)methodinA;
#end
//This is in protocol_B.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_B
-(void)methodinB;
#end
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
-(void)methodinC;
#end
i'm getting an exception , and my app is getting crashed...
***Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyClass 0X323nm31>setvalue:forundefinedKey:]:this class is not key value coding-compilant for the key window'.
Plz Tel me how to solve this problem??
So where you're getting this from (and the reason you're getting it 3 times) is you've got a mistake in your protocol definitions. You have:
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
{
}
-(void)methodinC;
#end
You can't declare class members in a protocol: only methods. Because of this, you don't need (and, as you've discovered) can't have the curly braces in the protocol definition. As such, you need this for your protocol definitions:
//This is in protocol_C.h file
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#protocol protocol_C
-(void)methodinC;
#end
Removing those should solve your issue.
When making new files, I always go through Xcode's new-class-files process, as it frequently gives you lots of convenient stuff. Here is the contents of a new protocol_D declaration fresh from Xcode:
#import <Cocoa/Cocoa.h>
#protocol protocol_D
#end
Hope this helps!
TL;DR: Protocol definitions can't have curly-braces anywhere in them.
Protocols generally go in a .h file; always go in a .h file if you plan on using them anywhere.
Just like everything else, you need to #import the .h file that contains the definition of the protocol before you use it.
So, in MyClass.h (it really should be capitalized -- Classes are always capitalized in Objective-C), #import the various protocol .h files.
Your protocol_A.h file declares conformance to protocol_B and protocol_C, yet you haven't imported the headers for protocol_B and protocol_C. This means that you are declaring conformance to protocols that as far as the compiler is concerned, don't exist in protocol_A.h. You need to import the headers:
In protocol_A.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "protocol_B.h" //note these new imports
#import "protocol_C.h"
#protocol protocol_A <protocol_B, protocol_C>
-(void)methodinA;
#end
Also see Apple's Communicating with Objects, which discusses delegates, protocols, and selectors. Though its listed under Mac OS X, most (if not all) appears to apply to iOS also.