Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Property that conforms to a Protocol and Class

Tags:

@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.

like image 253
keithbhunter Avatar asked May 28 '15 01:05

keithbhunter


People also ask

CAN protocols have properties in Swift?

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.

Can a protocol inherit from a class Swift?

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.

What's the difference between a protocol and a class in Swift?

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.

What is Swift protocol class?

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'.


1 Answers

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 UISliders. 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.

like image 114
keithbhunter Avatar answered Oct 24 '22 18:10

keithbhunter