0

The following is a workaround for the "problem" that protocols and their extensions in Swift do not store properties. It seems to "work" but I am wondering what reasons people might have for avoiding it?

fileprivate var strings: [String] = []

protocol SomeProat {
    func add(someString: String)
}

extension SomeProat {
    func add(someString: String) {
        strings.append(someString)
        print(strings)
    }
}

(I realise this question could be interpreted as subjective btw).

Joseph Beuys' Mum
  • 2,395
  • 2
  • 24
  • 50

1 Answers1

3

There is no good way to do what you're asking in pure Swift on non-Apple platforms.

If you are on an Apple platform (macOS, iOS, tvOS, watchOS), and your conforming type is a class, then you can use the associated object support provided by the Objective-C runtime:

import ObjectiveC

protocol MyProtocol: class {
    var strings: [String] { get }
    func add(someString: String)
}

private var MyProtocolSomeStringKey: UInt8 = 0

extension MyProtocol {
    var strings: [String] {
        get {
            return objc_getAssociatedObject(self, &MyProtocolSomeStringKey) as? [String] ?? []
        }
        set {
            let value = newValue.isEmpty ? nil : newValue
            objc_setAssociatedObject(self, &MyProtocolSomeStringKey, value, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    func add(someString: String) {
        strings.append(someString)
    }
}

class MyObject { }
extension MyObject: MyProtocol { }

let myObject = MyObject()
myObject.add(someString: "hello")
myObject.add(someString: "world")
print(myObject.strings)
// Output: ["hello", "world"]
rob mayoff
  • 375,296
  • 67
  • 796
  • 848