iOS - import vs forward declaration regarding setAlpha - ios

I'm trying to do some animations on an object that I have setup via IB. I'm adding a forward declaration to my .h like so:
#class MySpecialClass;
and then setup a property like so:
#property (nonatomic, retain) IBOutlet MySpecialClass *specialClass;
I want to be able to hide the specialClass using setAlpha, but I get the following error from xcode when trying to compile.
Receiver type 'MySpecialClass' for instance message is a forward declaration.
Do I need to import my class instead of a forward declaration? I'd like to not have to import anything unnecessary if I don't have to.

Forward declaration just tells the compiler, "Hey, I know I'm declaring stuff that you don't recognize, but when I say #MyClass, I promise that I will #import it in the implementation".
You use forward declaration to prevent stuff like circular includes (MyClass imports YourClass which imports MyClass which...), but the 'promise' you make with your code, is that you'll #import it later

You need to import it. Forward declaration is just to silence the compiler that this class exists, but it has no idea about its members, methods, properties, size...

Related

Forward declaration for classes called within method arguments of a protocol definition

Forward declarations are used to reduce dependencies and prevent unnecessary imports where multiple header files are involved.
This being said, how should I go about this scenario?
Let's say I have the following:
ClassAlpha.h
#interface ClassAlpha: NSObject
-(void)helloWorld;
#end
ProtocolA.h
#protocol ProtocolA <NSObject>
-(void)doSomethingWithAlpha:(ClassAlpha *__Nonnull)alpha;
#end
ClassBeta.h (conforms to ProtocolA)
#interface ClassBeta: NSObject<ProtocolA>
#end
ClassBeta.m
#import "ClassAlpha.h"
#implementation ClassBeta
-(void)doSomethingWithAlpha:(ClassAlpha *)alpha
{
NSLog(#"Hello");
}
#end
In ProtocolA.h, should I use a forward declaration of ClassAlpha? However, if I were to do so, that would mean that ClassBeta would have to be the one that imports ClassAlpha within its implementation, alongside importing ProtocolA. Alternatively, if I were to use the import statement of ClassAlpha within ProtocolA, needless to say ClassBeta woudldn't need to do so. What would be the best practice for this situation?
You should avoid #import in headers as much as possible. So, yes, you should use a forward declaration of ClassAlpha (i.e. #class ClassAlpha;) in PrototolA.h, because to use ClassAlpha * as a type in a parameter declaration, all you need to know is that ClassAlpha is the name of a class. You don't need to know anything else about how it is declared. Yes, you should import ClassAlpha.h in ClassBeta.m; you should do imports in implementation files as much as possible instead of header files.

Circular reference, Obj-C -> Swift, Swift -> Obj-C

I'm trying to create an Objc class, with a property of an enum type, where the enum type is created in swift. After this, I want to use the Objc class in Swift.
(Swift)Enum:
import Foundation
#objc enum AffectsUnit:Int {
case time
case person
case group
}
(Objc)class
#import "JSONModel.h"
#import "MyApp-Swift.h"
#interface AddPlayerToTime : JSONModel
#property (nonatomic) AffectsUnit affectsUnit;
#end
The Objc class has an empty method file.
So far, so good. No compiler warnings.
Since i also want to use my objc class in Swift. I need to import the class in my Bridging-Header.h.
#import "AddPlayerToTime.h"
Now my swift code can see the AddPlayerToTime class, but the project will no longer compile. The error I get is:
Unknown type name 'AffectsUnit'
I'm 99% sure it breaks because of circular reference. Since my swift code is importing AddPlayerToTime class and AddPlayerToTime is importing my swift code. But I do not know how to fix this. All post on this circular reference matter, seem to suggest using #class declaration. But since I'm trying to refer to an enum, not a class, this is not a solution for me.
Am I trying to accomplish something, that simple can't be done?
Edit1:
Please note: I want as much code as possible, to remain on the Swift side.
You should be able to move the enum declation over to the Obj-C side and still have it visible to Swift, like this:
typedef NS_ENUM(NSInteger, AffectsUnit)
{
AffectsUnitTime,
AffectsUnitPerson,
AffectsUnitGroup
};

iOS: forward declaration of non objects type class

I have property of type CLLocationCoordinate2D, how can I use forward declaration to declare that?
#class CLLocationCoordinate2D;
do not works
What you are looking for here is not forward declaration at all. You want to make use of the struct CLLocationCoordinate2D. First off that is not a class - for forward declaring structs look here.
BUT in your case you do not even have to use forward declaration since you only need to / have to include the correct header in your project. Namely CoreLocation:
#import CoreLocation;
or a little bit old fashioned
#import <CoreLocation/CoreLocation.h>
Additionally you probably have to add the CoreLocation framework as well if you have not done that already.

Forward class as super class

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.

Proper way to import delegate protocols

I try to import as very little as possible in my header files (using the implementation file instead), and for classes we can use #class, but what about protocols? If I try to declare a protocol that I'll be using in that header with #protocol I get a warning that "Cannot find protocol definition for '...'"
Is the proper way to handle this simply by importing the header that does the protocol declaration? (so one .h file imports the other .h)
Example for ListViewController.h:
#import <UIKit/UIKit.h>
#import "JTRevealSidebarV2Delegate.h" // is this the best way?
#class List;
#protocol JTRevealSidebarV2Delegate; // this produces a warning.
#interface ListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, JTRevealSidebarV2Delegate>
You need the #import. #protocol doesn't give the compiler enough information to do its type checking.
(When you declare a property of type List all it needs to know is that you really mean List and not, say, Lisp. A pointer to any object is the same size. A protocol, on the other hand, contains a list of stuff that a class needs to do. It needs to know what "stuff" is to do anything useful.)
It's correct, but if you want to get picky you can always create a single .h file where you declare your protocol only, and have both your ListViewController and JTRevealSidebarV2Delegate import it
Steps to do
make a protocol.h file declare your #optional methods etc
in your class A import protocol.h and implement the methods.
Use reference of the calss A's obj to call its methods of protocol from any place.

Resources