Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift protocol conformance by extension between frameworks

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.

like image 514
Cailean Wilkinson Avatar asked Feb 13 '18 09:02

Cailean Wilkinson


People also ask

Can a protocol extend a protocol Swift?

In Swift, you can even extend a protocol to provide implementations of its requirements or add additional functionality that conforming types can take advantage of. For more details, see Protocol Extensions. Extensions can add new functionality to a type, but they can't override existing functionality.

What is protocol conformance in Swift?

Any type that satisfies the requirements of a protocol is said to conform to that protocol. In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.

What are the functionalities of Swift extension?

In Swift, we can add new functionality to existing types. We can achieve this using an extension. Here, we have created an extension of the Temperature class using the extension keyword. Now, inside the extension, we can add new functionality to Temperature .

CAN protocol inherit from another protocol Swift?

One protocol can inherit from another in a process known as protocol inheritance. Unlike with classes, you can inherit from multiple protocols at the same time before you add your own customizations on top.


1 Answers

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.

like image 178
Cailean Wilkinson Avatar answered Nov 15 '22 03:11

Cailean Wilkinson