Given a declaration of a Swift class like
@objc(NSFoo) public class Foo {
public func bar() -> () {}
}
I would expect, from my reading of
Currently (in XCode8) this seems to have been addressed.
Defined in XYZLogger.h and XYZLogger.m
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(Logger)
@interface XYZLogger : NSObject
+ (void)verbose:(NSString *)logString;
+ (void)debug:(NSString *)logString;
+ (void)info:(NSString *)logString;
+ (void)warn:(NSString *)logString;
+ (void)error:(NSString *)logString;
@end
NS_ASSUME_NONNULL_END
Used in objc like this:
[XYZLogger debug:@"Hi from objective C"];
Used in Swift like this:
Logger.debug("Hi from swift");
Note: Things have change since this answer was first written - see updates at the end!
Yeah, this does seam to be a bug... though, controlling Obj-C runtime names of methods does work:
Say we define a pair of minimal Obj-C and Swift classes that interact with each other:
Foo.swift
import Foundation
@objc(SwiftFoo)
class Foo { // inheriting from NSObject makes no difference in this case
@objc(postcardFromSwift)
class func postcard() -> String {
return "Postcard from Swift!"
}
@objc(getMailInSwift)
class func getMail() {
if let hello = NSBar.postcard() { // NSBar is an Obj-C class (see below)
println("Printed in Swift: \(hello)")
}
}
}
NSBar.h
#import <Foundation/Foundation.h>
@interface NSBar : NSObject
+ (NSString *)postcard;
+ (void)getMail;
@end
NSBar.m
#import "NSBar.h"
#import "ObjS-Swift.h"
@implementation NSBar
+ (void)getMail {
// notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo)
printf("Printed in Objective C: %s", [[Foo postcardFromSwift] UTF8String]);
}
+ (NSString *)postcard {
return @"Postcard from Objective C!";
}
@end
If we now call their class methods, say, from main.m
:
#import <Cocoa/Cocoa.h>
#import "NSBar.h"
#import "ObjS-Swift.h"
int main(int argc, const char * argv[]) {
// notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo)
[Foo getMailInSwift];
[NSBar getMail];
return NSApplicationMain(argc, argv);
}
This prints the following:
// --> Printed in Swift: Postcard from Objective C!
// --> Printed in Objective C: Postcard from Swift!
But it shouldn't have! Foo
should only be visible to Obj-C as SwiftFoo
since that is what @objc(SwiftFoo)
is promising to do. Indeed, using SwiftFoo
triggers the Use of undeclared identifier
compiler error instead. The fact that this did work for method names, leaves little doubt that this is a bug. I am just amazed that you seem to be the first to ask about it! Plus one for that!
And yes:
// <#ModuleName#>-Swift.h
SWIFT_CLASS("SwiftFoo")
@interface Foo
+ (NSString *)postcardFromSwift;
+ (void)getMailInSwift;
... does seam to be inverted for the class name, yet this is how that macro works – see WWDC video Swift Interoperability In Depth (c. 45 min and c. 48 min into the video). The relevant documentation is Exposing Swift Interfaces in Objective-C.
Xcode 7 beta 4
The issue is now fixed (thanks to @ScottBerrevoets for the comment).
Xcode 7.1
(thanks to @Pang for the comment)
@objc class C { } // error: only classes that inherit from NSObject can be declared @objc