Forward declare structs in Objective C

2019-07-30 01:47发布

问题:

I'm writing an iOS app in which I have a model class that is going to initialize itself with an XMLElement I give to it.

I'm using TBXML for the XML part.

The header for the model class looks like this:

@interface CatalogItem : NSManagedObject

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSManagedObject *group;

-(id)initWithXMLElement:(TBXMLElement*)element;

@end

Now instead of including the header in which TBXMLElement is defined, I'd like to forward declare it with: struct TBXMLElement before the class definition. I'm however getting an "Expected Type" error wich tells me my declaration isn't working. Is this not how I would got about this?

As I understand it, including header files in header files is bad practice. The compiler doesn't need to know the inner workings of TBXMLElement, just that it exists or will exist at compile time.

回答1:

Forward declaration of structs are used all the time, but still involves importing a header. The motivation is to not allow developers to dip into the structure directly. I.e. look at CFString. It is implemented as a struct, but you can't touch the structure contents directly. Instead, there is a full API for manipulating the struct contents. This allows CFString's implementation details to change without breaking binary compatibility.

In your header (ideally the header that defines whatever API is associated with TBXMLElement*):

TBXMLElement.h:

typedef const struct TBLXMLElement *TBXMLElementRef;

extern TBXMLElementRef TBLXMLCreateElement();
... etc ...

Then, in the implementation file containing the implementation of the TBLXMLElementAPI:

TBXMElement.c (assuming it is a C file):

typedef struct __TBLXMLElement {
    ... struct members here ...
} TBLXMLElement;

TBXMLElementRef TBLXMLCreateElement()
{
     return (TBXMLElementRef)malloc(sizeof(TBLXMLElement));
}
... etc ....


回答2:

Are you sure it's a struct? Isn't it a class? Then the forward declaration would be @class TBXMLElement

If it's really a struct, just import the header where it is defined.