Swift Property that conforms to a Protocol and Class - ios

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

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.

It's not the ideal solution, but you can use a generic function instead of a generic class, like this:
class AClass: UIViewController {
#IBOutlet weak var anotherThing: UILabel!
private var thing: UIViewController?
func setThing<T: UIViewController where T: UITableViewDelegate>(delegate: T) {
thing = delegate
}
}

I came across the same issue, and also tried the generic approach. Eventually the generic approach broke the entire design.
After re-thinking about this issue, I found that a protocol which cannot be used to fully specify a type (in other words, must come with additional type information such as a class type) is unlikely to be a complete one. Moreover, although the Objc style of declaring ClassType<ProtocolType> comes handy, it disregards the benefit of abstraction provided by protocol because such protocol does not really raise the abstraction level. Further, if such declaration appears at multiple places, it has to be duplicated. Even worse, if multiple declarations of such type are interrelated (possibly a single object will be passed around them ), the programme becomes fragile and hard to maintain because later if the declaration at one place needs to be changed, all the related declarations have to be changed as well.
Solution
If the use case of a property involves both a protocol (say ProtocolX) and some aspects of a class (say ClassX), the following approach could be taken into account:
Declare an additional protocol that inherits from ProtocolX with the added method/property requirements which ClassX automatically satisfy. Like the example below, a method and a property are the additional requirements, both of which UIViewController automatically satisfy.
protocol CustomTableViewDelegate: UITableViewDelegate {
var navigationController: UINavigationController? { get }
func performSegueWithIdentifier(identifier: String, sender: AnyObject?)
}
Declare an additional protocol that inherits from ProtocolX with an additional read-only property of the type ClassX. Not only does this approach allow the use of ClassX in its entirety, but also exhibits the flexibility of not requiring an implementation to subclass ClassX. For example:
protocol CustomTableViewDelegate: UITableViewDelegate {
var viewController: UIViewController { get }
}
// Implementation A
class CustomViewController: UIViewController, UITableViewDelegate {
var viewController: UIViewController { return self }
... // Other important implementation
}
// Implementation B
class CustomClass: UITableViewDelegate {
private var _aViewControllerRef: UIViewController // Could come from anywhere e.g. initializer
var viewController: UIViewController { return _aViewControllerRef }
... // UITableViewDelegate methods implementation
}
PS. The snippet above are for demonstration only, mixing UIViewController and UITableViewDelegate together is not recommended.
Edit for Swift 2+: Thanks for #Shaps's comment, the following could be added to save having to implement the desired property everywhere.
extension CustomTableViewDelegate where Self: UIViewController {
var viewController: UIViewController { return self }
}

you can declare a delegate in Swift like this:
weak var delegate : UITableViewDelegate?
It will work with even hybrid(Objective-c and swift) project. Delegate should be optional & weak because its availability is not guaranteed and weak does not create retain cycle.
You are getting that error because there are no generics in Objective-C and it will not allow you to add #IBOutlet property.
Edit: 1. Forcing a type on delegate
To force that delegate is always a UIViewController you can implement the custom setter and throw exception when its not a UIViewController.
weak var _delegate : UITableViewDelegate? //stored property
var delegate : UITableViewDelegate? {
set {
if newValue! is UIViewController {
_delegate = newValue
} else {
NSException(name: "Inavlid delegate type", reason: "Delegate must be a UIViewController", userInfo: nil).raise()
}
}
get {
return _delegate
}
}

Related

Is it posible to create a default implementation of willSet on a class protocol

What I am trying to do is notify an object when it gets replaced as a delegate from my services object. I was wondering if there is a way to create a default implamintation of willSet so I do not have to duplicate code for each service object I create:
protocol BaseServiceDelegate: class {
var delegate: BaseServiceDelegate? {get set}
func servicesDelegateReferanceWasRemoved(service: BaseServiceDelegate)
}
extension BaseServiceDelegate {
willSet(newValue){
delegate?.servicesDelegateReferanceWasRemoved(self)
self = newValue
}
}
Im really not sure where to start with the syntax of the extension or if this is possible. The error with the above code is on the 'willSet' line: "Exspected declaration"
Thank you for your time
still not sure if its possible but i made some edits to insure you have access to the delegate object defined
the best answer I can find is to define a base Protocol:
protocol baseProtocol {
func informOfAction()
}
then implement this on your delegates that would like to also have this functionality:
protocol childProtocol: baseProtocol {
func somethingHappend()
func somethingElseHappend()
}
and when you create the object that conforms to childProtocol have the custom will set there
var delegate: childProtocol? {
willSet{
delegate?.informOfAction()
}
}
not as nice as i was looking for but not too bad, an extra 3 lines on all my objects similar to 'delegate'

How can I create a Set of delegate protocol items in Swift?

Let's assume I have five UIView objects which all conform to a particular protocol. I have an object which should maintain a list of these objects, and message them all when necessary.
protocol MyProtocol: AnyObject {
func doSomething()
}
The problem is, when I go to add these UIViews to a Set variable, the compiler produces an error because MyProtocol does not conform to Hashable. I can understand the reasoning for this, can anyone think of good ways to overcome this? In the meantime I considered using NSHashTable instead, but you lose the nice enumeration features of Sets.
Updating answer to post some sample code (this is still not working)
protocol MyProtocol: class, AnyObject {
func doSomething()
}
class MyClass {
var observers: Set<MyProtocol> = Set<MyProtocol>()
}
As you are defining protocol for class so you need to write 'class' keyword before inheriting any other protocol:
protocol MyProtocol: AnyObject, Hashable{
func doSomething()
}
class MyClass<T: MyProtocol> {
var observers: Set<T> = Set<T>()
}
Change your protocol to this and it will work fine.
You can refer Apple Documentation for further details.

How to use multiple protocols in Swift with same protocol variables?

In swift I'm implementing two protocols, GADCustomEventInterstitial and GADCustomEventBanner.
Both of these protocols require a property called delegate. delegate is a different type in each protocol, and thus a conflict arises.
class ChartBoostAdapter : NSObject, GADCustomEventInterstitial, GADCustomEventBanner, ChartboostDelegate{
var delegate:GADCustomEventInterstitialDelegate?; // Name conflict
var delegate:GADCustomEventBannerDelegate?; // Name conflict
override init(){
}
...
}
They are libraries/frameworks it's not my definition
Then obviously you cannot make the same class adopt both protocols. But you don't really need to. Just separate this functionality into two different classes, as is evidently intended by the designer of these protocols. You are supposed to have one class that adopts GADCustomEventInterstitial and has its delegate, and another class that adopts GADCustomEventBanner and has its delegate. What reason do you have for trying to force these to be one and the same class? As in all things where you are using a framework, don't fight the framework, obey it.
It is actually possible, I just encountered same situation. I had two different but kind of related protocols. In some cases I needed both to be implemented by delegate and in other cases only one and I didn't want to have two properties eg... delegate1, delegate2.
What you need to do is create another combined protocol that inherits from both protocols:
protocol ChartBoostAdapterDelegate: GADCustomEventInterstitialDelegate, GADCustomEventBannerDelegate { }
class ChartBoostAdapter : NSObject, GADCustomEventInterstitial, GADCustomEventBanner, ChartboostDelegate {
weak var delegate: ChartBoostAdapterDelegate?
override init(){
}
...
}
The simple answer is that you can't.
Maybe one protocol depends on another, in which case you would use the dependent protocol for the type of your delegate.
Note that this can be solved using Mixins (possible since Swift 2.0) if you are in a Swift-only environment. It just cannot be solved as long as you need to have the code bridged to Obj-C, as this problem is unsolvable in Obj-C. Yet that can usually be solved by a wrapper class, which I will show later on.
Let's break this down to a minimalist example:
import Foundation
#objc
protocol ProtoA {
var identifier: String { get }
}
#objc
protocol ProtoB {
var identifier: UUID { get }
}
#objc
class ClassA: NSObject, ProtoA, ProtoB {
let identifier = "ID1"
let identifier = UUID()
}
The code above will fail as no two properties can have the same name. If I only declare identifier once and make it a String, compiler will complain that ClassA does not conform to ProtoB and vice verse.
But here is Swift-only code that actually does work:
import Foundation
protocol ProtoA {
var identifier: String { get }
}
protocol ProtoB {
var identifier: UUID { get }
}
class ClassA {
let stringIdentifier = "ID1"
let uuidIdentifier = UUID()
}
extension ProtoA where Self: ClassA {
var identifier: String {
return self.stringIdentifier
}
}
extension ProtoB where Self: ClassA {
var identifier: UUID {
return self.uuidIdentifier
}
}
extension ClassA: ProtoA, ProtoB { }
Of course, you cannot do that:
let test = ClassA()
print(test.identifier)
The compiler will say ambigous use of 'identifier', as it has no idea which identifier you want to access but you can do this:
let test = ClassA()
print((test as ProtoA).identifier)
print((test as ProtoB).identifier)
and the output will be
ID1
C3F7A09B-15C2-4FEE-9AFF-0425DF66B12A
as expected.
Now to expose a ClassA instance to Obj-C, you need to wrap it:
class ClassB: NSObject {
var stringIdentifier: String { return self.wrapped.stringIdentifier }
var uuidIdentifier: UUID { return self.wrapped.uuidIdentifier }
private let wrapped: ClassA
init ( _ wrapped: ClassA )
{
self.wrapped = wrapped
}
}
extension ClassA {
var asObjCObject: ClassB { return ClassB(self) }
}
If you put it directly into the class declaration of ClassA, you could even make it a stored property, that way you don't have to recreate it ever again but that complicates everything as then ClassB may only hold a weak reference to the wrapped object, otherwise you create a retain cycle and neither of both objects will ever be freed. It's better to cache it somewhere in your Obj-C code.
And to solve your issue, one would use a similar wrapper approach by building a master class and this master class hands out two wrapper class, one conforming to GADCustomEventInterstitial and one conforming to GADCustomEventBanner but these would not have any internal state or logic, they both use the master class as storage backend and pass on all requests to this class that implements all required logic.

Override var conforming to a protocol with a var conforming to a child of the overridden var protocol

This is my inheritance structure
Protocols
protocol BaseProtocol {
}
protocol ChildProtocol: BaseProtocol {
}
Classes
class BaseClass: NSObject {
var myVar: BaseProtocol!
}
class ChildClass: BaseClass {
override var myVar: ChildProtocol!
}
I'm receiving a compiler error:
Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!'
What is the best approach to achieve this?
UPDATE
I updated the question trying to implement the solution with generics but it does not work :( This is my code (now the real one, without examples)
Protocols
protocol TPLPileInteractorOutput {
}
protocol TPLAddInteractorOutput: TPLPileInteractorOutput {
func errorReceived(error: String)
}
Classes
class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput {
var output: T!
}
And my children
class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput {
}
Well, inside my TPLAddInteractor I can't access self.output, it throws a compiler error, for example
'TPLPileInteractorOutput' does not have a member named 'errorReceived'
Besides that, when I create the instance of TPLAddInteractor
let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor()
I receive this other error
Generic parameter 'T' cannot be bound to non-#objc protocol type 'TPLAddInteractorOutput'
Any thoughts?
#tskulbru is correct: it can't be done, and this has nothing to do with your protocols. Consider the example below, which also fails…this time with Cannot override with a stored property 'myVar':
class Foo {
}
class Goo: Foo {
}
class BaseClass: NSObject {
var myVar: Foo!
}
class ChildClass: BaseClass {
override var myVar: Foo!
}
To understand why, let's reexamine the docs:
Overriding Properties
You can override an inherited instance or class property to provide
your own custom getter and setter for that property, or to add
property observers to enable the overriding property to observe when
the underlying property value changes.
The implication is that if you are going to override a property, you must write your own getter/setter, or else you must add property observers. Simply replacing one variable type with another is not allowed.
Now for some rampant speculation: why is this the case? Well, consider on the one hand that Swift is intended to be optimized for speed. Having to do runtime type checks in order to determine whether your var is in fact a Foo or a Bar slows things down. Then consider that the language designers likely have a preference for composition over inheritance. If both of these are true, it's not surprising that you cannot override a property's type.
All that said, if you needed to get an equivalent behavior, #tskulbru's solution looks quite elegant, assuming you can get it to compile. :)
I don't think you can do that with protocols
The way i would solve the problem you are having is with the use of generics. This means that you essentially have the classes like this (Updated to a working example).
Protocols
protocol BaseProtocol {
func didSomething()
}
protocol ChildProtocol: BaseProtocol {
func didSomethingElse()
}
Classes
class BaseClass<T: BaseProtocol> {
var myProtocol: T?
func doCallBack() {
myProtocol?.didSomething()
}
}
class ChildClass<T: ChildProtocol> : BaseClass<T> {
override func doCallBack() {
super.doCallBack()
myProtocol?.didSomethingElse()
}
}
Implementation/Example use
class DoesSomethingClass : ChildProtocol {
func doSomething() {
var s = ChildClass<DoesSomethingClass>()
s.myProtocol = self
s.doCallBack()
}
func didSomething() {
println("doSomething()")
}
func didSomethingElse() {
println("doSomethingElse()")
}
}
let foo = DoesSomethingClass()
foo.doSomething()
Remember, you need a class which actually implements the protocol, and its THAT class you actually define as the generic type to the BaseClass/ChildClass. Since the code expects the type to be a type which conforms to the protocol.
There are two ways you can go with your code, depending what you want to achieve with your code (you didn't tell us).
The simple case: you just want to be able to assign an object that confirms to ChildProtocol to myVar.
Solution: don't override myVar. Just use it in ChildClass. You can do this by design of the language Swift. It is one of the basics of object oriented languages.
Second case: you not only want to enable assigning instances of ChildProtocol, you also want to disable to be able to assign instances of BaseProtocol.
If you want to do this, use the Generics solution, provided here in the answers section.
If you are unsure, the simple case is correct for you.
Gerd

Swift 2.2: Accessing/Modifying Class Variables from Class Protocol

I've been digging around and can't quite seem to find an answer to this... I am trying to implement something like the simplified protocol setup below.
//PROTOCOL SETUP
protocol myProtocol: class {
var thisVariable: CustomType? {get set}
}
extension myProtocol {
func doSomeThings() { //IMPLEMENTATION SPOT 1// }
}
extension theClassIAmUsing: myProtocol {
func doSomeThings() { //IMPLEMENTATION SPOT 2// }
}
//NEW IN SWFIT
extension myProtocol where Self: theClassIAmUsing {
func doSomeThings() { //IMPLEMENTATION SPOT 3// }
}
//CLASS:
class theClassIAmUsing: UIView, myProtocol {
var thisVariable: CustomType? = CustomType() //etc...
//does not implement doSomeThings() but is available
init() {
//some init
}
}
The implementation I am trying to use is performing logic/function based on:
self.thisVariable!.element
and IT WORKS! but only in IMPLEMENTATION SPOTS 2 and 3...
The point of my question is, if I'm subclassing UIView for use around my application, I will need to add an extention of myProtocol "where Self:" is (the next custom class) EVERY TIME I create a new subclass....... (yea this cleans up the class definition code section but seems tedious.)
It may be picky, by wouldn't it seem reasonable to be able to access self.thisVariable in an extention of the protocol so that it may be used in all of my subclassed UIViews??
Am I missing something?
The error I get in IMPLEMENTATION SPOT 1 is:
warning: could not load any Objective-C class information.
This will significantly reduce the quality of type information available.

Resources