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.
Related
I'm just a newbie who follow iOS dev, and when I create new single application by using Xcode, I notice that #interface AppDelegate() being declared again in AppDelegate.m file.
but to be honest, I really don't understand why, I already see #import "AppDelegate.h" at begin of AppDelegate.m file, why couldn't I directly use #implementation AppDelegate after #import "AppDelegate.m"?
There is a difference here. The declaration of the AppDelegate Interface in the .m file is actually a class extension. Notice the () after the interface declaration.
As mentioned in the documentation:
Class extensions are often used to extend the public interface with
additional private methods or properties for use within the
implementation of the class itself.
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
I have a class (MyClass) with a lot of methods. Consequently, the .m file has become quite difficult to read. I'm relatively new to Objective-C (having come from REALbasic) and I was wondering if it's possible to put some of the methods in MyClass into different files and then include them in the class. How would I go about this in Xcode?
Yes it is possible and fortunately this can be done easily in Objective-C with Categories.
Say you have your base class MyClass.
#interface MyClass : NSObject
-(void) methodA;
#end
And the according implementation file (not relevant here).
Then you can create a category by defining a new interface in a new header file:
// the category name is in parenthesis, can be anything but must be unique
#interface MyClass (extended)
-(void) methodB;
#end
and the implementation file:
#implementation MyClass (extended)
-(void) methodB {
}
#end
Common convention to name these files is ClassToAddMethodsTo+CatgoryName, i.e.:
MyClass+extended.h
MyClass+extended.m
Group related functionality into categories and give it a meaningful name.
In Objective-c you can break a class into 'categories' - a class spread across many files. The normal Object-Oriented way is to use SuperClasses and SubClasses.
This is almost certainly a code smell telling you that you have a design problem. See this antipattern
There is one thing you could do..........
But be warned, some might consider this pure blasphemy. :)
Say you have a class with two methods you want to have in separate files.
You'll have three files:
• Class.h
• Class.m
• Class_otherMethod.m
Your Class.h should look just like any other. I think it's better to keep the header file complete, but this 'trick' can work on separating .h files just as well.
#interface Class : NSObject
- (void) method;
- (void) otherMethod;
#end
In your Class.m file you will #include the Class_otherMethod.m inside the Class #implementation like this:
#import "Class.h"
#implementation Class
- (void) method {
// do something.
}
#include "Class_otherMethod.m"
#end
And your Class_otherMethod.m file will have only the bare otherMethod implementation:
- (void) otherMethod {
// do something different.
}
Why this works
It's quite simple actually. The preprocessor simply "pastes" the content of Class_otherMethod.m inside the Class.m file and the compiler treats it as one big long file. :P
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.
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