Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference class definition from prefix header in swift

I'm adding swift code to an existing Objective-C project. I'm having problems referencing a definition from the existing prefix header.

I have a class called MyClass, defined in Objective-C with .h:

@interface MyClass
+(instancetype)myClass;
-(void)doStuff;
@end

And .m:

@implementation MyClass
+ (instancetype) myClass
{
    // More to it than this, but this illustrates the setup
    return [[MyClass alloc] init];
}

- (void)doStuff
{
    // Do something interesting
}
@end

The prefix header MyProj-Prefix.pch contains:

#define MYCLASS MyClass
#define SOMEVAR @"Hello"

I have created a bridging header which contains:

#import "MyProj-Prefix.pch"

The project contains Objective-C code that uses the class definition, e.g.

[[MYCLASS myClass] doStuff];

I would like to mirror this in my new swift code. I can see and reference the defined variable, but the defined class isn't visible. e.g.

let someStr = SOMEVAR // This compiles
MYCLASS.myClass.doStuff() // MYCLASS isn't visible

Any pointers on how to achieve this? I'm not even sure if this is possible in swift.

like image 374
Gabrielle Earnshaw Avatar asked Nov 08 '22 13:11

Gabrielle Earnshaw


1 Answers

This problem would exist even if #define MYCLASS MyClass was in any other header, not necessarily in prefix header. This is because preprocessor directives are generally not imported into Swift. Simple macros are, however, imported if they can be mapped to global constants, which is possible for SOMEVAR, but not MYCLASS. See https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-ID17 .

One could use a typealias in Swift at the global scope:

typealias MYCLASS = MyClass

Of course, the typealias would have to be modified if MYCLASS was re-defined in the header.

This approach is not very helpful, unfortunately, if the definition of MYCLASS changes depending on where/how the code is built. However, since the code must know quite a bit about the behavior common to the various classes that can be defined as MYCLASS, it might be possible to use protocols here, for example.

UPDATE: After thinking about/playing with it some more and reading some other posts, e.g. Using obj-c typedef in Swift, here is a better solution, I think. With this approach you don't need to change your Swift code if MYCLASS is re-#defined in Objective-C.

Somewhere in your Objective-C code, e.g. in the bridging header, add

typedef MYCLASS * _MYCLASS;

which will then allow you to do things like the following in Swift:

_MYCLASS.myClass().doStuff()

If you really insist on using MYCLASS in Swift for some reason, adding typealias MYCLASS = _MYCLASS in your Swift code will do the trick.

like image 195
Anatoli P Avatar answered Nov 15 '22 06:11

Anatoli P