Search code examples
iosobjective-cswiftcocoa-touchnsbundle

Dynamically loaded Swift framework bundle's principalClass is NIL


A rare case when an iOS app needs to load/execute/unload bundle code on demand. While it works with an Objective-C framework, Swift framework proves to be a hurdle: Bundle.principleClass consistently returns nil.

I have followed the example in this blog post Plugin Architecture in Swift(ish) plus some other sources like this Apple forum post.

What is needed is 3 individual projects (not 3 targets within single project):

FrameworkSwift - framework A
FrameworkObjC - framework B
Main App - loads frameworks on demand

You can checkout the code here:

  1. Main app

  2. Objective-C framework

  3. Swift framework

Xcode project setup:

Xcode project setup looks like so

If you try to build and run, the console will tell the story:

Loaded bundle: FrameworkObjC.framework , principal class: PluginObjC
Loaded bundle: FrameworkSwift.framework , principal class: N/A

A few details about the Swift framework:

  • class is public and extends NSObject
  • principal class is set in Info.plist
  • frameworks not linked, they are embedded as binaries
  • the frameworks projects dragged into the main project

Solution

  • The name of the principal class in the Info.plist for the Swift Framework should begin with its module name. In other words, if you change principal class from "PluginSwift" to "FrameworkSwift.PluginSwift in the Info.plist, the call to principalClass will return the class instead of nil.