If you want to add stored properties using extensions, here's a little trick I used that allows you to do it for base classes that you can override (namely view controllers, which is the one I used it for):
This protocol allows a base class to be extended with stored properties in extensions and in protocols:
protocol ExtensibleObject:class
{
var extendedProperties:[String:Any] { get set }
}
extension ExtensibleObject
{
func get<T>(_ defaultValue:T, _ file:String = #file, _ line:Int = #line) -> T
{
return (extendedProperties["\(file):\(line)"] as? T) ?? defaultValue
}
func set<T>(_ newValue:T, _ file:String = #file, _ line:Int = #line)
{
return extendedProperties["\(file):\(line)"] = newValue
}
}
To use the protocol, you need to create a subclass of the base class to add storage for all extended properties (for the class and all its sub classes).
class ExtensibleViewController:UIViewController, ExtensibleObject
{
var extendedProperties:[String:Any] = [:]
}
Note that you can do it directly in the base class if it is yours.
You would then use the "extensible" base class for your own subclass instead of the base class:
class MyVC:ExtensibleViewController
{}
From then on, any of the subclass can receive new "stored" properties in extensions:
extension MyVC
{
var newStoredProperty:Int
{ get { return get(0) } set { set(newValue) } } // set and get must be on same line
}
Stored properties can also be added through protocol adoption for classes implementing the ExtensibleObject protocol:
protocol ListManager:ExtensibleObject
{
var listContent:[String] { get set }
}
extension ListManager
{
var listContent:[String]
{ get { return get([]) } set { set(newValue) } }
}
extension MyVC:ListManager {}
Bear in mind that these extended properties behave as lazy variables and that they have some additional overhead when used. For UI components and view controllers, this is usually not a problem.