Can a Swift Package include a table view?

Hi,
I'm trying to convert a Carthage framework with resources to a Swift Package. My framework includes a view with a UITableView and a xib file containing a single UITableViewCell view. The view for the table view loads properly but when the table view attempts to dequeue a table view cell and reference an IBOutlet in the cell's class, it will crash. Should this be possible in a SPM now that resources are supported?

If I remove any outlets in the UITableViewCell, the dequeue works correctly and I can see the cell's view loaded into the table view. The issue appears to be around recognizing the class associated with the UITableViewCell in the Xib file.

The console includes the following error:

[Storyboard] Unknown class _TtC39SPMTableViewCellXib_SPMTableViewCellXib20XibTestTableViewCell in Interface Builder file.

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UITableViewCell 0x12df14d20> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key titleLabel.'

Here's an example repo to replicate the issue:

Including this package in an app and calling TestXibLoading.beginViewDisplay(self) to begin loading and displaying the table view will trigger the crash.

Any help is greatly appreciated!

1 Like

Seems like the mangled name is incorrect:

xcrun swift-demangle _TtC39SPMTableViewCellXib_SPMTableViewCellXib20XibTestTableViewCell
_TtC39SPMTableViewCellXib_SPMTableViewCellXib20XibTestTableViewCell ---> SPMTableViewCellXib_SPMTableViewCellXib.XibTestTableViewCell

It should just be SPMTableViewCellXib.XibTestTableViewCell and I was able to reproduce the issue with your project.

I think the issue lies in the "Inherit Module From Target" checkbox, once customModuleProvider="target" was gone from the .xib, I was able to run your project successfully.

2 Likes

Unchecking that checkbox and leaving the default module name fixed this issue. Thanks so much!

Is this behavior intended or a bug? In the sample project above, I noticed unchecking this box isn't required for the View.xib to be able to find the ViewController class associated with it.

1 Like

I'm not sure if there's a bug here to be honest, my experience with Interface Builder is a bit limited. It might make sense to file a feedback report for Xcode on this.

1 Like

Using the Objective-C name solve the issue.

Example:

@objc(SPMXibTestTableViewCell)
class XibTestTableViewCell: UITableViewCell {
}

SPM is the class prefix used because Objective-C does not have namespaces or module names.

In interface builder set the target to none and uncheck Inherit Module From Target and set the name of the class, in this case SPMXibTestTableViewCell .

I think this happen because when creating an Xcode project the module name becomes the project name i.e: SPMTableViewCellXib but when in Swift PM mode the module name becomes: SPMTableViewCellXib_SPMTableViewCellXib where the first part is the module name and the second part (text after the underscore _) is the target.

This might be due to having 2 build systems used by Xcode that are functioning differently and independently.

Just in case, I faced it as well, and if I understand it correctly, it's not "mangling" per se that is wrong, rather IB compiler (ibtool) is given wrong module name when compiling .xib. Basically, from what I can see for a module Foo it's invoked like

/Applications/Xcode.app/Contents/Developer/usr/bin/ibtool --errors --warnings --notices --module Foo_Foo ...

(Note Foo_Foo as the module name).

I guess this has something to do with the fact that for Swift modules, there's a separate target for building the resources bundle, i.e. in the above case the target name is 'Foo_Foo' (hence we get Foo_Foo.bundle). Then "Inherit Module from Target" in Interface Builder just does what it says: it derives "Foo_Foo" from the target name.

So, I feel like the "problem" is probably "due" to the target name used when building the module resource bundle. Probably this nuance was basically overlooked by the folks who added support for bundling resources in SPM.

Ah, sorry, missed the last comment from @karhm - I believe it basically says the same, I just added some explanation on "why".

Perfect solution!! I unchecked "Inherit Module From Target" and selected the default module name, and voila! Problem solved!!