Importing Swift types exposed in an Objective-C API back into Swift

Hey. I was wondering about resurfacing a Swift type in an Objective-C API: how intentional is it that it works in the compiler, and whether there are any plans to support/deprecate this behavior in one of SwiftPM's build systems in the future.

Here is my setup. I have a Swift target called SwiftTarget with the following source:

import Foundation

@objc public class SwiftTargetType : NSObject {
    @objc public func exposeToObjectiveC() {}
    public func exposeToSwift() {}
}

This type is returned/consumed from an Objective-C target ObjcTarget with the following source:

// ObjcTarget.h
@import SwiftTarget;

SwiftTargetType * useSwiftTargetFromObjC(SwiftTargetType *);

// ObjcTarget.m
#import ObjcTarget.h

SwiftTargetType * useSwiftTargetFromObjC(SwiftTargetType * arg) {
    [arg exposeToObjectiveC];
    // the exposeToSwift API is not accessible here as expected
    return arg;
}

Then, finally, I have a Swift target called SwiftConsumer with the following source:

import ObjcConsumer

func useSwiftTarget(arg: SwiftTargetType) {
    let returnedFromObjC = useSwiftTargetFromObjC(arg)
    // Here I want to have access to the Swift API again
    returnedFromObjC.exposeToSwift()
}

What I find currently with Xcode targets is, that if I switch all the right DEFINES_MODULE and the SWIFT_INSTALL_OBJC_HEADER, then this works exactly as I want it to. Something that seems to be a requirement is that the Swift compiler must be able to see the modular import of SwiftTarget, and just the @class SwiftTargetType forward declaration makes the Objective-C API non-importable.

With SwiftPM, this doesn't seem to work out of the box. If I define the package with the SwiftTarget and the ObjcConsumer .targets, then I can get this to work in an Xcode Swift target if I hack this a bit by using -Xcc -fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/SwiftTarget.modulemap in OTHER_SWIFT_FLAGS. I couldn't find an easy way to make this work with all targets defined in SwiftPM.

This leaves me wondering: will such a setup be supported or deprecated in the future? Will it be supported to work out of the box in SwiftPM?

1 Like

IIUC, for Xcode build of SwiftPM targets, this issue might be fixed in Swift Build, so I created an issue in the swift-build repository: Enable Swift types exposed in Objective-C APIs to be visible to the Swift consumer · Issue #956 · swiftlang/swift-build · GitHub