@property (strong, nonatomic) UIViewController<UITableViewDelegate> *thing;
I want to implement a property like in this Objective-C code in Swift. So here is what I've tried:
class AClass<T: UIViewController where T: UITableViewDelegate>: UIViewController { var thing: T! }
This compiles. My problem comes when I add properties from the storyboard. The @IBOutlet
tag generates an compiler error.
class AClass<T: UIViewController where T: UITableViewDelegate>: UIViewController { @IBOutlet weak var anotherThing: UILabel! // error var thing: T! }
The error:
Variable in a generic class cannot be represented in Objective-C
Am I implementing this right? What can I do to fix or get around this error?
EDIT:
Swift 4 finally has a solution for this problem. See my updated answer.
A protocol can have properties as well as methods that a class, enum or struct conforming to this protocol can implement. A protocol declaration only specifies the required property name and type.
Protocols allow you to group similar methods, functions, and properties. Swift lets you specify these interface guarantees on class , struct , and enum types. Only class types can use base classes and inheritance from a protocol.
You can create objects from classes, whereas protocols are just type definitions. Try to think of protocols as being abstract definitions, whereas classes and structs are real things you can create.
Protocol is used to specify particular class type property or instance property. It just specifies the type or instance property alone rather than specifying whether it is a stored or computed property. Also, it is used to specify whether the property is 'gettable' or 'settable'.
Update for Swift 4
Swift 4 has added support for representing a type as a class that conforms to a protocol. The syntax is Class & Protocol
. Here is some example code using this concept from "What's New in Swift" (session 402 from WWDC 2017):
protocol Shakeable { func shake() } extension UIButton: Shakeable { /* ... */ } extension UISlider: Shakeable { /* ... */ } // Example function to generically shake some control elements func shakeEm(controls: [UIControl & Shakeable]) { for control in controls where control.isEnabled { control.shake() } }
As of Swift 3, this method causes problems because you can't pass in the correct types. If you try to pass in [UIControl]
, it doesn't have the shake
method. If you try to pass in [UIButton]
, then the code compiles, but you can't pass in any UISlider
s. If you pass in [Shakeable]
, then you can't check control.state
, because Shakeable
doesn't have that. Swift 4 finally addressed the topic.
Old Answer
I am getting around this problem for the time being with the following code:
// This class is used to replace the UIViewController<UITableViewDelegate> // declaration in Objective-C class ConformingClass: UIViewController, UITableViewDelegate {} class AClass: UIViewController { @IBOutlet weak var anotherThing: UILabel! var thing: ConformingClass! }
This seems hackish to me. If any of the delegate methods were required, then I would have to implement those methods in ConformingClass
(which I do NOT want to do) and override them in a subclass.
I have posted this answer in case anyone else comes across this problem and my solution helps them, but I am not happy with the solution. If anyone posts a better solution, I will accept their answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With