Forward class as super class - ios

I am trying to do a static library, which uses AFNetworking. I want to distribute the library only with .a and .h files.
However, one of my classes within the library is a subclass of AFHTTPSessionManager. So my previous .h file looked like this:
#import <Foundation/Foundation.h>
#import "AFNetworking.h"
#interface MyClass : AFHTTPSessionManager
+ (MyClass *) sharedInstance;
- (void) doMagic;
#end
When I compiled the library and imported the .a and .h files into a new test project I got an error "Lexical or Preprocessor Issue 'AFNetworking.h' file not found". Thought that the solution would be to use forward class declaration and move the #import "AFNetworking.h" to the .m file like this:
#import <Foundation/Foundation.h>
#class AFHTTPSessionManager;
#interface MyClass : AFHTTPSessionManager
+ (MyClass *) sharedInstance;
- (void) doMagic;
#end
Unfortunately, this approach throws an error "Attempting to use forward class 'AFHTTPSessionManager' as superclass of 'MyClass'".
As far as I understand forward class declaration you use it just to say "hey compiler classXXX exists, but you cannot see its methods and properties". Therefore, I am not sure if that's the solution to my problem.
Any suggestion how to subclass from a class but not import it?

You can't subclass a class whose header is unavailable. The best you can do is to make your subclass of AFHTTPSessionManager private and instead expose a class (a subclass of NSObject, say) which acts as a facade, forwarding messages to your private class.
You can also use a protocol as the interface for your class and just expose a method which returns an id<MyClassProtocol>. Something like:
#protocol MyClassProtocol
- (void) doMagic;
#end
id<MyClassProtocol> GetSharedInstance();
And then have a class like this which is not exposed from your library:
#interface MyClass<MyClassProtocol>: AFHTTPSessionManager
// ...
#end
Which you can instantiate and return from GetSharedInstance.

You should be importing the class here, not forward declaring it. Any class that uses your subclass should also have access to all of the public methods and variables part of the superclass without having to then also import it manually. The first error you mentioned shows that either your class is not included in the target or perhaps you are importing it wrong.
How are you including AFNetworking. Are you using cocoapods?
If so, try importing it this way.
#import <AFNetworking.h>
Otherwise, make sure that AFNetworking.h is actually part of your build target using the File Inspector Panel on the right side of Xcode.

Related

Is it possible to use extension methods which are added at implementation file rather than interface file in objective c?

This is header file/Interface file(className.h).
Here printSomething method is declared as an extension. And I'll call it later in main.m
extension.h
#import <Foundation/Foundation.h>
#interface extension_class : NSObject
#end
#interface extension_class () // This is the external method which is added using extension
- (void) printSomething;
#end
This is the Implementation file(className.m). Here printSomething method is defined.
extension.m
#import "extensions.h"
#implementation extension_class
- (void) printSomething
{
NSLog(#"I'm the method defined inside extension class but declared by using extensions");
}
#end
So far everything works fine. Now My question is simple why can't I access that printSomething method if I declare(until now declaration and definition was not done in same file) it in implementation file. As in the below code snippet? (Please compare and observe the changes among above two .h and .m files with below ones to get my point)
extension.h
#import <Foundation/Foundation.h>
#interface extension_class : NSObject
#end
extension.m
#import "extensions.h"
#interface extension_class () // This is the external method which is added using extension
- (void) printSomething;
#end
#implementation extension_class
- (void) printSomething
{
NSLog(#"I'm the method defined inside extension class but declared by using extensions");
}
#end
This is main method which is common in both cases.
main.m
#import "extensions.h"
int main()
{
#autoreleasepool
{
extension_class *object = [[extension_class alloc]init];
[object printSomething];
}
return 'O';
}
So what is point in having extensions in objective C if it doesn't allow us to add methods anywhere we like? or Is there any other method to achieve what I said above?
You're free to define extensions in the .m file. This is incredibly common. Those extensions won't generally be known to importers of the .h file, so they won't easily be callable from other files. That's a good thing. It lets us make "private" extensions, which is very useful and common.
They're not really private. Anything can call anything in ObjC. Outside callers just won't know about the method. But they can declare the method themselves as a category (note the text inside the parentheses) and call it:
OtherClass.m
#import "ExtensionClass.h"
#interface ExtensionClass (ThingsIKnowYouHave)
- (void) printSomething;
#end
...
[extensionClass printSomething];
Or they could of course just call it directly without declaring it (though this can cause ARC problems, so avoid this in modern ObjC):
[(id)extensionClass printSomething];
Or they could call it as a selector (again, this can cause ARC problems; so using the category is best):
[extensionClass performSelector: NSSelectorFromString(#"printSomething")];
There's really not much point to creating extensions in the header file (i.e. "public" extensions). If it's in the header file, you might as well just put it in the interface. The most common use of extensions (basically why they were invented), is so you can define methods inside the implementation file.
Extensions shouldn't be confused with categories, where there is text inside the parentheses. These were created to help organize large classes, and later were used for "informal protocols" before #optional was added. Extensions can add methods directly to the base class. Category interfaces just say "this method might exist." Extension interfaces are formal continuations of the primary interface (the compiler requires that they be implemented).
For more on categories and extensions, see Customizing Existing Classes in the Programming with Objective-C guide. See also Defining Classes in the same guide, which may clear up some confusion I believe you have about header files and interfaces.

Issues with including header files

In my application I have several classes, that cross-over with each other. I need to connect this classes and create properties of them, but some classes are not visible for another, I suppose that main issue here is in including header files.
class MyOperationQueue
#import <Foundation/Foundation.h>
#import "ContentTableView.h"
//#import "CustomTableViewCell.h"
//#import "ObjectForTableCell.h"
#interface MyOperationQueue : NSOperation
#property(assign, nonatomic) BOOL isCancelled;
#property(strong, nonatomic) ContentTableView* tableView; //unknown type name
class ObjectForTableCell
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "MyOperationQueue.h"
#interface ObjectForTableCell : NSObject
#property (strong, nonatomic) MyOperationQueue* currentQueue;//unknown type name
class ContentTableView - here I don't have warnings
#import <UIKit/UIKit.h>
#import "CustomTableViewCell.h"
#import "Protocol.h"
#import "MyOperationQueue.h"
#import "ObjectForTableCell.h"
#import "ImageViewController.h"
#interface ContentTableView : UITableViewController<CellDelegate, NSURLSessionDataDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate>
Stick a #class MyOperationQueue; above
#interface ObjectForTableCell : NSObject
to make it:
#class MyOperationQueue;
#interface ObjectForTableCell : NSObject
Here is an excerpt from official documentation here:
Referring to Other Classes
An interface file declares a class and, by importing its superclass,
implicitly contains declarations for all inherited classes, from
NSObject on down through its superclass. If the interface mentions
classes not in this hierarchy, it must import them explicitly or
declare them with the #class directive:
#class Rectangle, Circle;
This directive simply informs the
compiler that “Rectangle” and “Circle” are class names. It doesn’t
import their interface files. An interface file mentions class names
when it statically types instance variables, return values, and
arguments. For example, this declaration mentions the NSColor class.
Since declarations like this simply use the class name as a type and
don’t depend on any details of the class interface (its methods and
instance variables), the #class directive gives the compiler
sufficient forewarning of what to expect. However, where the interface
to a class is actually used (instances created, messages sent), the
class interface must be imported. Typically, an interface file uses
#class to declare classes, and the corresponding implementation file
imports their interfaces (since it will need to create instances of
those classes or send them messages).
The #class directive minimizes the amount of code seen by the compiler
and linker, and is therefore the simplest way to give a forward
declaration of a class name. Being simple, it avoids potential
problems that may come with importing files that import still other
files. For example, if one class declares a statically typed instance
variable of another class, and their two interface files import each
other, neither class may compile correctly.
There is also an excellent article (by NSHipster) on various other compiler directives here. I recommend reading it, for this knowledge will likely serve you well in the future.
Sometimes things get messed up when you create circular imports, i.e. MyOperationQueue.h and ContentTableView.h import each other.
A common fix is to remove at least one of those imports and replace them with forward declaration of the classes, i.e. add #class ContentTableView; to MyOperationQueue.h.
You should then import ContentTableView.h in your implementation file MyOperationQueue.m, so that the whole interface is known. This typically also helps reduce compile time.

Subclassing view controller: Forward declaration

I have been following the rule of having:
#MyClassName in the header file of a class
&&
#import "MyClassName" in the implementation
I have now decided to subclass one of my view controllers. If I overwrite a method then I get the following message:
Receiver 'MyClassName' for class message is a forward declaration
To over come this I need to put the #import into the header file which doesn't seem to follow what I thought was best practices.
Can someone explain if I have misunderstood the use of #class?
Or if I am dong things correctly, can someone please explain you need to break best practices and use #import in header file when subclassing?
Many thanks.
Edit:
Thanks for the answers. I think I need to add some more detail to clarify my situation and hopefully my understanding. Here is my header for my base class:
#import <UIKit/UIKit.h>
#import "CorePlot-CocoaTouch.h"
#class Organisation;
#interface LongCallDetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
In my impementation I have
#import "Organisation.h"
My subclass header contains the following:
#import "LongCallDetailViewController.h"
#interface LongCallSubclassViewController : LongCallDetailViewController
#end
If I override a method in the subclass and try to use an Organisation object it gives me the error as I stated above. Therefore I either need to add #import "Organisation.h" into the base classes header or duplicate the #import "Organisation.h" into the subclasses implementation file. Both of which seem wrong to me.
Many thanks.
Within header files, you should be importing other header files for any classes you subclass. You do not need to import header files for classes that are just referenced and not subclassed. For example, a header file might look like:
#import "MySuperClass.h"
#class MyObjectType;
#interface MySubClass : MySuperClass
#property (strong) MyObjectType *value;
#end
Edit:
Based on your new edits, it looks like you are writing your header files correctly. When you only declare #class in a scope, you will not be able to access any of the selectors or properties associated with that class. It is okay to declare using #class in places where you are not intending to use selectors or properties of that class type and just pass around a reference (as in the header I have described above), but as soon as you want to do anything else with the object, you'll need to have imported the header file describing the #interface.
When defining a #class MyObjectType in a header file, it is generally expected that the #import "MyObjectType.h" appears in the associated source file. Header files are intended as a declaration of structure, whereas source files will contain the implementation. For example, the source file associated with the header file I described above might look like:
#import "MySubClass.h"
#import "MyObjectType.h"
#implementation MySubClass
- (void)overriddenFunction {
[self.value anObjectTypeSelector];
}
#end
You shouldn't think about "duplicating" an import statement when they're in two different scopes. When you forward declare #class Organisation in your LongCallDetailViewController header file, you'll have a #import "Organisation.h" in your LongCallDetailViewController source file. If you also need to access this object's properties and selectors in your LongCallSubclassViewController class, you'll need to #import "Organisation.h" in your LongCallSubclassViewController implementation file. Remember: the implementation files do not know about the content of each other; they only know about the contents of the header file.
#import imports definition of class with all public methods and properties.
#import predeclare class, so there is no information about methods and properties
You use #import when:
You subclass a class - other classes importing your class need to know about all methods that class suport.
You implement a protocol - same reason as above.

Import useless headers

I have a big project which is refactored a lot.
Some classes import unnecessary headers.
#import "someClass1.h"
#import "someClass2.h"
#import "someClass3.h"
f.e:
classA in interface has:
#import "classB.h"
#import "classC.h"
classB in interface has:
#import "classC.h"
So that import classC in classA interface could be removed...
I would like to have my project clean and tidy.
I'm just wondering:
Is there a way to find useless imports quickly?
What is best way for such situations and organizing one interface import of other interfaces?
Does it affect on application performance if you have plenty of useless/duplicated imports?
Any help appreciated
1) No there is no a way you need to check if that import is used in your file (use find function for this);
2) The best way is import UNTIL IS POSSIBLE header in implementation file (.m). If you need to declare that class in your header file (.h) you can use:
#class nameClass
before begin with #interface...etc.
If you already know that instead you need to import that class header file in your header, you can do it. Be careful to avoid #import cycle. In fact suppose to have this situation:
MGCustomViewController.h:
#import "MGViewController.h"
#interface MGCustomViewController : UIViewController
#end
MGViewController.h:
#import "MGCustomViewController.h"
#interface MGViewController : MGCustomViewController
#end
This cause an error at compile time, because you inherit from MGCustomViewController but importing MGCustomViewController.h you are importing again this last header before that the compiler read the #interface MGCustomViewController directive and so will show an error that says something like SUPERCLASS NOT FOUND.
3) No, but effects on the compile time.

Cocos2D/iOS: usage of "#class Component" tag

I am using Cocos2d 2.x and iOS 5.0.
Could anyone share with me a good tutorial or explanation on the usage of "#class Component" tag?
Is there any design/patter that refers to it or does it do something more specific to the code?
I haven't found much on my google search.
#class just tells the compiler that the name following it is the name of an Objective-C class. It's used in .h files when it's necessary to define a symbol of that type but where importing the entire definition would either be overkill or cause an actual problem. (For example, two classes that each refer to the other.)
The way it works is that normally if you reference a class in an interface, you have to #import that class' header file:
#import "OtherClass.h"
#interface MyClass : NSObject
{
OtherClass* someOtherClass;
}
#end
The #class statement allows you to skip importing the header:
#class OtherClass;
#interface MyClass : NSObject
{
OtherClass* someOtherClass;
}
#end
You still have to #import "OtherClass.h" in the implementation file if you use #class.
// Still need to import, but now any class importing MyClass.h
// does not automatically know about OtherClass as well.
#import "OtherClass.h"
#implementation MyClass
…
#end
When you #import "MyClass.h" somewhere else in a third class, that third class does not automatically include the header of the OtherClass class if you have used #class OtherClass; in the MyClass header. Therefore the third class has no knowledge of OtherClass unless it expressly imports the OtherClass.h header. This is helpful when writing a public API that should hide its implementation details (ie OtherClass) from the developer.
Forward declaration is considered good practice (if only because it has no downsides other than a slightly altered workflow) and is preferable to importing the class' header in another header file. This certainly helps prevent cyclic imports as mentioned by Phillip.
I don't know about Xcode but in Visual Studio (C++) class forwarding was also instrumental to speed up compilation in larger projects with hundreds of classes. That was because the VS C++ compiler spent quite some time resolving header dependencies

Resources