Unable to import ObjC interface from a package in a public ObjC file in a framework

Problem Statement:

  • Unable to import .h file from an ObjC SPM to a .h file in an ObjC file in a framework with mix of ObjC and Swift code
  • The issue is: in order to support access of ObjC file in Swift code in a framework we need to use umbrella header (in place of bridging header). Once the file is imported in Umbrella header and made public it will no longer allow import of .h file from package in its interface

Project Structure:

a. Package: ObjCPackage

ObjCPackage

|- Package.swift

|- ObjCPackage

  • MathsUtilities.h (class interface)

  • MathsUtilities.m (class implementation)

  • NiceLogs.h (protocol)

b. Project: ObjCSwiftFramework

ObjCSwiftFramework

|- ObjCSwiftFramework.h (umbrella header)

|- Calculation.h (objc class interface)

|- Calculation.m (objc class implementation)

|- SwiftCalci.swift (swift class)

Details:

  • #import <ObjCSwiftFramework/Calculation.h> added in ObjCSwiftFramework.h as Calculation has to be used in SwiftCalci
  • Calculation.h marked as public in target membership in Xcode so that it can be added in umbrella header ObjCSwiftFramework.h
  • #import "NiceLogs.h" in Calculation.h gives error

Here is a small sample which I created to demonstrate the problem: ObjCSwiftFramework

Upon reviewing the issue, I believe the linking between Swift and Objective-C should be straightforward, given that the Objective-C package has a good umbrella header file. A bridging header should have been automatically generated during the project setup, allowing you to import the Objective-C file into Swift.

Assuming your project language is Swift, and you're aiming to integrate an existing Objective-C package, you can refer to Apple's documentation for more details on importing objectives-c frameworks: Using Frameworks in Swift.

Here are a couple of things to check and consider:

  • Ensure that the bridging header file is indeed generated and complied correctly. You can check this in Build Phases, under Headers Search Paths.
  • Double-check that the protocol you are trying to access is included in the Objective-C umbrella header. Alternatively, you could create a new .swift file that just imports the necessary headers and exposes the protocol to Swift.
  • I noticed that there doesn’t seem to be a target set up to run the example or test the ‘Calculation()’ function. You could add a quick playground or a test target to verify that everything is working correctly after including the framework.

In this case, it seems like the recommendation works, or I don't see the issue as just adding the import from the external module that contains the protocol will allow you to compile the framework; however, there is no target to run it in this case on the project you shared, nor is there a way to test the result of Calculation().printInt(). Could you please share the error messages or any specific compilation problems you are encountering? Additionally, a screenshot of the Xcode project setup could be invaluable.

import Foundation
import ObjCPackage //<—— Added

class SwiftCalci {
    func doSomething() {
        Calculation().printInt() // This gives compilation error. Method belongs to ObjCPackage-NiceLogs protocol
        Calculation().helloWorld() // This compiles fine. Method belongs to InternalProtocol
    }
}

But you should also fulfill the requirements of the protocol:

@implementation Calculation
- (void)printInt { 
    NSLog(@"Here it is: %d", [MathsUtilities getHardcodedInt]);
}
- (void)helloWorld {
    NSLog(@"Hello World");
}

A few notes. Since you are using an ObjC package, create a Package.swift file if it does not exist already and register your ObjC headers as public. It seems like you already added a Package.swift file. Hopefully, with posting in the forums, you can provide other developers who consume and create Objective-C frameworks to share their experiences and expertise in this thread.

Unable to import ObjC interface from a package in a public ObjC file in a framework
 
 
Q