Objective-C use of #import and inheritance - objective-c

I have a hypothetical UIViewController class named "foo". foo inherits from class bar and class bar #import's "Class A", a class which foo uses extensively. The problem is, when I'm using an instance of class A in foo, I don't get any compiler errors, but I do get a warning for instance, that an instance of Class A does not respond to a particular method. Do I have to explicitly #import ClassA.h into class 'foo'? even though class foo extends extends bar, which already imports it?
Hope that's not too confusing. Let me know if I need to clear anything up.

It sounds like you have a circular dependency issue. In order to resolve it, yes, each imlementation file (.m) needs to #import the proper header file. However, if you try to have the header files #import each other, you'll run into problems.
In order to use inheritance, you need to know the size of the superclass, which means you need to #import it. For other things, though, such as member variables which are pointers, or methods which take as a parameter or return the other type, you don't actually need the class definition, so you can use a forward reference to resolve the compiler errors.
// bar.h
#class A; // forward declaration of class A -- do not to #import it here
#interface bar : UIViewController
{
A *member; // ok
}
- (A) method:(A)parameter; // also ok
#end
// bar.m
#import "bar.h"
#import "A.h"
// can now use bar & A without any errors or warnings

Related

ObjC: must I specify the inheritance in the header file?

Common examples for a ObjC object are like this (for the header file):
#interface A: B {
int x;
int y;
}
#end
Is it possible to avoid the inheritance specification (i.e. B here) in the header file?
In my case, the framework A defines that class A and another (sub-)framework B defines the class B (which is a subclass of NSView). A links to B. In my application, I link to A and I don't need to know anything about B except that it is a subclass of NSView. And I want to avoid to link to B. But if B is in the header file, I think I cannot avoid it, that's why I was asking about how to avoid it.
No. You have to specify the superclass for any subclass. May I ask why you would want to do something like this?
Your application will need the code for B, therefore you must either link to B's framework, or compile the B framework into your A framework. Either way, you cannot use an instance of A without the code for B, and you must include B's header in your A header.
no.
you must often work around this with a class cluster, hold a private implementation, or create an object factory. then you can minimize the dependencies across modules.
you'll still ultimately need to link to the sub library at some stage if you intend to use it (e.g. create an instance of).
Update - Demonstrate Private Implementations
Private implementations can be entirely opaque. If you do expose them, here are two ways to implement private implementations which are visible to clients:
via protocol:
// MONDrawProtocol.h
// zero linkage required
// needs to be visible to adopt
// may be forwarded
#protocol MONDrawProtocol
- (void)drawView:(NSView *)view inRect:(NSRect)rect;
#end
// MONView.h
#protocol MONDrawProtocol;
#interface MONView : NSView
{
NSObject<MONDrawProtocol>* drawer;
}
#end
// MONView.m
#include "MONDrawProtocol.h"
#implementation MONView
- (void)drawRect:(NSRect)rect
{
[self.drawer drawView:self inRect:rect];
}
#end
via base:
// MONDrawer.h
// base needs to be visible to subclass and types which use MONDrawer
// may be forwarded
#interface MONDrawer : NSObject
- (void)drawView:(NSView *)view inRect:(NSRect)rect;
#end
// MONView.h
#class MONDrawer;
#interface MONView : NSView
{
MONDrawer * drawer;
}
#end
// MONView.m
#include "MONDrawer.h"
#implementation MONView
- (void)drawRect:(NSRect)rect
{
[self.drawer drawView:self inRect:rect];
}
#end
If you don't specify a superclass in the interface, then your class is a root class. This means it doesn't inherit from any other class, so it is responsible for providing its own implementation of the required methods (most of those defined by the NSObject class and protocol). Since this is not a simple task, it is highly encouraged that you inherit from some other class which provides these methods.
Yes you can, with that you will also lost default implementations of alloc, init, etc. Which makes you write your own alloc, init and other stuffs which was there in NSObject
can't you just include a mock version of the class you're inheriting from A's header itself? Not sure if that will cause problems, but it would allow you to clean up your linking requrirements a bit. B-new could then be a category of B'Original
I have one solution now. Instead of providing the class, I just provide a function like this:
NSView* allocA();
Internally in the framework A, A is a subclass of B.

xcode import corresponding files

I get an error when I try and import corresponding files.
i.e.
UIViewController "VC.h" Imports "CustomObject.h"
CustomObject Imports "VC.h"
Starts giving error expected specifier qualifier list before
Any ideas? I want both objects to be able to call each other.
Thanks
You have a circular dependency. You need to break the circular dependency by using a forward declaration. A forward declaration says "this is the name of something, but I don't know the full definition of it".
For example:
// In VC.h
// Forward declaration of an Objective-C class. After this, you can now use
// pointers to CustomObject, but you can't cell methods or access properties
// of those objects
#class CustomObject;
#interface MyViewController
{
CustomObject *obj;
}
#end
Then, in the implementation files, you can include both header files with no problems.
Thanks for the detailed response.
This was the solution, I just did not understand fully the first time I read it.
//VC.h calls cannot be made to CustomObject here, however there is not really any need to
#class CustomObject;
#interface VC : ViewController {
CustomObject* gameController;
// ...
//VC.m calls made in .m only.
#import "CustomObject.h"
gameController = [CustomObject init];
and vice versa in CustomObject
Sorry I didn't post this as a reply to your answer, new here :S

Cocoa: Build Warning that s Forward Declared Class's and #interface May not Exist

I am trying to build the Clustering Plug in my project under Leopard. I have following two questions.
In the project an interface class is defined as
#interface ClusteringController : NSWindowController
{
.......
.....
....
}
#end.
And this class is used in implementation class using forward declaration:
#class ClusteringController;
then in one function it is used as:
- (long) filterImage:(NSString*) menuName
{
ClusteringController *cluster = [[ClusteringController alloc] init];
[cluster showWindow:self];
return 0;
}
When I build this project it produces the warning:
warning: receiver 'ClusteringController' is a forward class and corresponding #interface may not exist
Also there is one more warning produced:
warning: no '-updateProxyWhenReconnect' method found
This warning is coming for the following line of code:
if(delegate) [delegate updateProxyWhenReconnect];
Can anybody help me to overcome these warnings?
A forward declaration is used when the header file will be imported after the interface. It looks to me that you've used the #class directive after the interface for the class itself.
The normal use of a forward class declaration looks like this:
#import "SomeSuperClass.h"
#class Forwardclass;
#interface SomeClass : SomeSuperClass
{
Forwardclass anIvar;
}
#property Forwardclass anIvar;
#end
#import "SomeClass.h"
#import "ForwardClass.h"
#implementation SomeClass
#synthesize anIvar;
-(void) setAnIvar:(ForwardClass *) aForwardClass;
#end
The #class directive is never used in an implementation (.m) file.
That's not what #class is for.
You use #class in the header file for another class, to tell the compiler that the class you're declaring does exist. Without it, the compiler would not know that that's a class name, and when you declare a variable as holding a pointer to an instance of that class, the compiler would think that you're just making up words. Using #class is called forward-declaring the class.
Your situation is different. You're in the implementation file for that class.
What the compiler needs from you now is the class's #interface. The warning is telling you that the compiler needs an #interface, but you haven't given it one (so, as far it knows, the #interface “may not exist”).
Normally, you would have written the #interface in a header file; how now to get it into the implementation file?
That's where the preprocessor comes in, with its #import directive. At the top of the implementation file (ClusteringController.m), import the header file:
#import "ClusteringController.h"
The preprocessor will replace this with the contents of that file, then hand the preprocessed code to the compiler, which will see the #interface there.

Proper way to structure classes in Xcode framework

I'm building a custom Xcode framework, and I have a class called AXController that has a class method called showActivationWindow. showActivationWindow initializes and shows a window using AXWindowController which is a subclass of NSWindowController. Then, AXWindowController calls activate which is a class method in AXController on a button press in the window it displays.
I included AXWindowController.h in AXController.h and included AXController.h in AXWindowController.h so each could access the other's methods, but this is throwing a lot of Xcode warnings. It also seems like a very inelegant solution.
What is the correct way to solve this problem?
It's not a good idea to import header files recursively. There's a directive #class (link to Apple doc) which tells that there is a class named as such. In practice the usage is something like A.h
#class B;
#interface A:NSObject {
B* anInstanceOfB;
}
...
#end
and B.h
#import "A.h"
#interface B:NSObject {
A* anInstanceOfA;
}
...
#end
Then you can import A.h and B.h as you like from your .m file! But be careful not to make a retain cycle, if you don't use garbage collection.

How do I declare a child class as a property of a parent class to be used in related child classes?

I have a small class hierarchy where I would like to have a child class be a property of it's parent class and all related subclasses. Essentially,
I have AbstractClass with a
property of GroupClass.
GroupClass is a child of
AbstractClass.
UsableObjectClass is a child of
AbstractClass and uses
GroupClass.
If I do the following...
#import <Cocoa/Cocoa.h>
#import "GroupingClass.h" // I've bounced this between #class as well.
#interface myAbstractClass : NSObject {
GroupingClass* parentGroup;
}
#property (readwrite, assign) GroupingClass* parentGroup;
#end
#import "myAbstractClass.h" // ERROR LOCATION
#implementation myAbstractClass
#synthesize parentGroup;
#end
#import <Cocoa/Cocoa.h>
#interface GroupingClass : myAbstractClass {
}
#end
#import <Cocoa/Cocoa.h> // ERROR LOCATION IN ALL CHILD CLASSES OF AbstractClass
#interface GroupingClass : myAbstractClass {
}
#end
...I get this funky "Line Location GroupingClass.h:3: error: cannot find interface declaration for 'myAbstractClass', superclass of 'GroupingClass'" at the noted error locations.
I've tried various ways of getting this to work (yes, I know the above is totally wrong), Categories and Protocols seems the be right direction but this is becoming only so much flailing around now, and I really just need a shove in the right direction. I think I'm missing something grossly fundamental (frankly, I'm a little embarrassed to be asking this question).
I'm currently porting this application from REALbasic and something like this was a breeze; I could just add the property as the child class and it just worked. Objective-C...not so much.
Any help, even just a hint, is greatly appreciated!
You should be able to use a #class declaration in your header and import the subclass's header in your implementation file.
What you're looking for is a "forward class declaration". At the top of the AbstractClass header, add
#class GroupingClass;
This tells the (unfortunately slightly archaic) C compiler that there will be a class called GroupingClass and that it can allocate space for variables of that type appropriately.
You have what is called a circular reference or dependency. Your base class is dependent upon its child class, which is in turn dependent upon the base class.
I suggest you heavily reconsider your class structure.