Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed language framework

I have a framework (let's call it MyKit) written in Objective-C that I'm extending with some Swift classes. I'm trying to get my head around it using this documentation: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_77

As far as I understand, I'm not supposed to have a bridging header class, and instead put all my includes in the umbrella header file (that I understand to be ).

So I write in MyKit.h:

#import <MyKit/ModelObjectA.h>
#import <MyKit/ModelObjectB.h>
#import <MyKit/ControllerObjectC.h>

I don't list ControllerObjectD.swift, even though it goes into here as well? Or should I include

#import <MyKit/ControllerObjectD-Swift.h>

?

ControllerObjectD uses ModelObjectA and ModelObjectB. Now that I don't have a bridge headerfile, I get compile errors in it because it cannot find these objects.

The documentation says "Swift will see every header you expose publicly in your umbrella header." and this is true when I import the framework into other projects, but the framework project cannot compile because it doesn't see it. I have turned on the "Define Modules" build setting.

Is there something I've misunderstood about the umbrella header, perhaps? Where can I say "hi project, this is the umbrella header file"? The framework compiles if I set the umbrella header file as bridging header, but that sounds like I've come back to the beginning this way?

Cheers

Nik

like image 835
niklassaers Avatar asked Feb 27 '15 08:02

niklassaers


1 Answers

I believe your problem may be down to the Access Modifiers in your Swift class, however I've written a short guide and sample project to help you:

Sample project can be found here

There are two parts to having a mixed language framework:

  1. Importing Objective-C into Swift
  2. Importing Swift into Objective-C

1. Importing Objective-C into Swift

This is, for example, if you have an Objective-C class named Player that you want to add to a swift class called Game.

According to the documentation, you need to do these two steps to import the Player object into the Game object.

  1. Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to Yes.

Defines Module

  1. In your umbrella header file, import every Objective-C header you want to expose to Swift.

    #import <Framework/Player.h>
    

Make sure your Player header file in Objective-C is marked for public target membership in the framework:

Public Header File Setting

Following these steps, it's possible to import the Player Objective-C class into the Game Swift Class:

import UIKit

public class Game: NSObject {
    public let player: Player

    public init(player: Player) {
        self.player = player
        super.init();
    }
} 

2. Importing Swift into Objective-C

For importing the Swift Game class into the Player object, we can follow a similar procedure.

  1. As before; Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to Yes.

Defines Module

  1. Import the Swift code from that framework target into any Objective-C .m file within that framework target using this syntax and substituting the appropriate names:

    #import <ProductName/ProductModuleName-Swift.h>
    

    In my case, this works as:

    #import <SwiftObjC/SwiftObjC-Swift.h>
    

    and I assume, for you:

    #import <MyKit/MyKit-Swift.h>
    

    Therefore, make sure that all the properties, methods and classes you want to access are defined as public in your swift file or else they won't be visible to Objective-C .

I have uploaded my sample project showing how this all works on GitHub https://github.com/elliott-minns/SwiftObjCTestFramework

I hope this helps you with your problem.

like image 97
Elliott Minns Avatar answered Nov 16 '22 00:11

Elliott Minns