-5

I have created an protocol extension of UIImageView and added a bool property isFlipped to the extension. My problem is that if I set isFlipped true of false for one object is sets the same values for the all the UIImageView objects. Can anyone guide how to handle it separately for each UIImageView objects.

protocol FlipImage {

var isFlipped: Bool { get set }

}
var flippedValue = false

extension UIImageView:FlipImage{
var isFlipped: Bool {
    get {
        return  flippedValue
    }
    set {
        flippedValue = newValue
    }
  }
}
shallowThought
  • 19,212
  • 9
  • 65
  • 112
Sishu
  • 1,510
  • 1
  • 21
  • 48
  • 2
    There is only one global variable flippedValue. – The solution is exactly what was suggested in the answer to your previous question http://stackoverflow.com/questions/44063181/protocol-extension-in-swift-3. – Martin R May 19 '17 at 12:11
  • But in my previous question how to make a property in extensions but here My problem is how to handle it for each objects . Because if i use subclassing it will be treated as separate property for each objects. I want to do it using POP. – Sishu May 19 '17 at 12:22
  • 2
    I don't get it. You *cannot* add stored properties in an extension. Using associated objects is a workaround for that problem. What *exactly* does not work with the solution given in the answer? – Martin R May 19 '17 at 12:41
  • Thanks Martin! But by subclassing we can fix it, So if I have to add some functionalities in existing class like UILabel, UIImageView what would be the better approach for that. – Sishu May 19 '17 at 12:48

1 Answers1

1

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.

Alain T.
  • 40,517
  • 4
  • 31
  • 51