4
votes

For various reasons I'm splitting the codebase for a Swift iOS app into a series of modules, mostly dependent in a fairly linear fashion. The basis of this question is: If I have a class in one module, and then extend it to conform to a protocol in another module, will all objects of that type conform automatically?. Let's call them Module 1 & Module 2 for now.

A consequence of this modularisation that not every cell for a given UITableView class will be declared within that same module. so to allow me to use cells from outwith that module I've declared a series of protocols describing the basic functions of a cell. For example:

In module 1:

public protocol ActionableCell {
    func performAction()
}

Which is used by the tableview so every time a cell is selected, if it conforms to ActionableCell then performAction() is called on it. This allows the tableview to handle taps on cells it does not know about.

So, in the tableview's class (Module 1):

open class SomeTableView: UITableView {
    // Blah

        open override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // If the cell is actionable, inform it that it has been selected
    if let cell = tableView.cellForRow(at: indexPath) as? ActionableCell {
        cell.performAction()
    }
}

However, sometimes the cell is declared in Module 1, but the action is not possible without some module further down the chain, so in Module 1 I declare the class:

open class SomeCell: UITableViewCell {
}

Then in module 2 I make that cell conform to ActionableCell.

extension SomeCell: ActionableCell {
    func performAction() {
        // Do Stuff
    }
}

So, just to clarify:

In the first module: ActionableCell is declared, SomeTableView is declared, SomeCell is declared but does not conform to ActionableCell.

Then in the second module: SomeCell is extended to conform to ActionableCell

If both modules are included & built in my project, but Module 2 is not directly imported in the Swift file either in the tableview class (where the cast to ActionableCell is performed), or where the cell is created, will the cell conform to ActionableCell anyway, because the extension is part of the project? If not, at what point is it important to import the extension?

I know that accessing the extended properties of SomeCell is not possible without importing the second module, but this is about whether it can be cast without importing the extension.

1

1 Answers

5
votes

I've realised this didn't receive any answers, and I've been using this method for a while now, so I thought I should post an answer.

It turns out class extensions are global - if one module extends a class, it is extended for every module by the virtue of that module being present. This is independent of whether the second module is imported, only on it being installed.

So, e.g. if Module A contains class Foo, and Module B extends Foo to conform to some protocol (e.g. Hashable). If Module A then checks for Hashable conformance, it will find that Foo does indeed conform if and only if Module B is also present.