Using a Swift Package in a mixed Swift and Objective-C project

Hello,

I apologize in advance if this question has been asked before (I searched the forum but did not find anything).

On a brand new project, I created swift sources and Objective-C sources and made sure they worked together. I then proceeded to create a new local Swift Package in Xcode 11 beta 4 with a single Swift file that defined a NSObject subclass with a string inside.
When I tried to use the package class from the project Swift code, it went fine, as expected, after importing the module. I then tried using the package class from the project Objective-C code and no matter what, I could not make it work.

Is this expected behavior? If so, why? And why doesn't a '#import "Package-Swift.h"' or 'import <Package/Package-Swift.h>' in the .m file where I want to use the package code solve the problem?

Thank you for the clarification.

4 Likes

This is a known issue. You can't import a Swift package target into an Objective-C target right now.

1 Like

Thank you for the quick response.
Is there a Jira ticket that we can follow regarding a future implementation of this feature? Is there a timeframe for it?

3 Likes

Clearly "Swift" packages are meant to be used with Swift code and all new development should be done in Swift but this makes it really difficult to add features into existing projects where the code path runs through ObjC code. I'm just curious as to why this doesn't "just work"; I know nothing about the internals of SPM.

Are there any details about this or a JIRA task associated with it? We're looking to migrate to using packages sometime in the future and we're trying to plan a path forward, not being able to import Swift targets into ObjC targets in a large roadblock to that.

This required some work in the build system. At a higher level, SwiftPM needed to ask the Swift compiler to emit an ObjC compatibility header file which can be used by the ObjC targets.

I landed support for this in master couple of days ago.

10 Likes

That's amazing! I guess two follow up questions:
Any idea on availability within Xcode? (sort of apple-specific question I guess)
Also the PR mentions it being only for macOS is there a purpose for this? Our case would be iOS/iPadOS.

Edit: I just realized that comment may be pertaining to the build agent, as in, only SPM implementations built using macOS would see this functionality since it's the only place ObjC is accessible. Is that correct to say?

2 Likes

I'm having the same issue.

It looks like it has already been fixed but isn't available yet (likely at least until after Nov 5 when 5.2 is cut). Whatever Xcode version first adopts 5.2 I imagine would have this functionality.

The real question is is it possible to download the latest toolkit and test this functionality within Xcode now?

2 Likes

Just fyi, this issue is resolved in Xcode 11.4.

6 Likes

If the SwiftPM is responsible for generating the header file, how do you reference it from an Xcode project? Is this done automatically?

I ask, because I see a number of examples online where a Run Script step is required to get ahold of the the header files, and I'm wondering if this is available when using SwiftPM.

It should just be implicitly through the module import. The reason those kind of scripts exist I believe is because in the past those compatibility header files weren't generated. Now if I have Swift module FooSwift and import it into my .m ObjC file in FooObjC like so @import FooSwift; it should see everything made available to ObjC from FooSwift. Someone else can correct me if I'm wrong I've just done a few preliminary tests with a mix of library types.

1 Like

I had my 'C' head on, and I was using #import instead of @import.

Thanks for the suggestion!

Update: on further inspection, it seems that I was mislead by the documentation, which recommends using #import for in project and framework Swift code. See https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c . I guess they need a special section for Swift Packages

2 Likes

Does it work in Xcode11? Because I have some problem. I have class defined in Package

@objc public class ObjCCountry: NSObject {
    @objc public let id: Int
    @objc public let title: String
    @objc public func getTitle() -> String { title }
    @objc public func printTitle() { 
        print("title: \(title)")
    }
    public init(id: Int, title: String) {
        self.id = id
        self.title = title
    }
}

And no one of these properties and methods I could not see in .mm file

  #import "SearchCountries-Swift.h"
     ...
  ObjCCountry *z = [gate getCountry];
  NSLog(@"run, z: %@", z.title); // Property 'title' cannot be found in forward class object 'ObjCCountry'

While Option+Click on ObjCCountry and Jump to Definition sends me to the source code in the package

Terms of Service

Privacy Policy

Cookie Policy