2

I have two classes I want to use in my new class. The first one implements a swipe to delete and the second enables a long press gesture:

class DeleteItem: UITableViewCell {
}

class OpenDetail: UITableViewCell {
}

Since Swift doesn't allow a class to inherit from multiple classes the following example obviously won't work:

class ItemViewCell: DeleteItem, OpenDetail {
}

So in order to create ItemViewCell and having both options, I'll have to have one of the classes to inherit from each other:

class DeleteItem: UITableViewCell {
}

class OpenDetail: DeleteItem {
}

class ItemViewCell: OpenDetail {
}

The problem is, if I only want the long press gesture I'll have to create a new class without inheriting from DeleteItem. Is there a better way of doing this?

Laap
  • 71
  • 1
  • 7
  • [Yes](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Extensions.html). – Tobi Nary Jan 28 '16 at 09:57
  • @JanGreve: Do you mind showing me an example how to achieve this using extensions? In my project it gives me an error. – Laap Jan 28 '16 at 10:04
  • 1
    Can't you make `DeleteItem` and `OpenDetail` protocols, rather than classes? – Tim Vermeulen Jan 28 '16 at 10:40
  • The only solution is to either subclass `OpenDetail` to add swipe implementation or subclass `DeleteItem` to add long press. Both classes are probably overriding the same method (e.g. `awakeFromNib`). – Sulthan Jan 28 '16 at 11:52
  • I'm not sure if my understanding of a `protocol` is correct, but isn't a protocol "simply" something an object has to conform to? I.e: the variables / functions declared in the protocol should be mandatory in the object to make it conform the protocol. In that case, I have no idea how to make `DeleteItem` and `OpenDetail` a protocol since it's far more complicated than that. Simply said, both `Delete` and `Open` is mainly about the gesture recognizer and the handling of this gesture (moving the table view cell etc). – Laap Jan 28 '16 at 14:18
  • @Laap did you find a solution for this? – Anjan Biswas Oct 09 '17 at 22:01

1 Answers1

4

This is the perfect case for using Protocols and Protocol extension. A swift protocol is like an interface in Java for example. A protocol can define a set of functions which has to be implemented by the entities which want to conform to this protocol, moreover a protocol can define properties which has to be present in these entities too. For example:

protocol ItemDeleter {
  var deletedCount: Int {get set}
  func deleteItem(item: ItemType)
}

The problem is, that each entity would have to provide its own implementation of func deleteItem(item: ItemType) even if multiple entities share the same logic of deleting an item, this where a protocol extension comes in handy. For example:

extension ItemDeleter {
  func deleteItem(item: ItemType) {
    // logic needed to delete an item

    // maybe incremented deletedCount too
    deletedCount++
  }
}

Then you could make your ItemViewCell conform to the ItemDeleter protocol, in this case all you need is to make sure that ItemViewCell has a property deletedCount: Int. It does not need to provide an implementation for func deleteItem(item: ItemType) as the protocol itself provides a default implementation for this function, however you can override it in your class, and the new implementation will be used. The same applies for DetailOpener protocol.

ysholqamy
  • 221
  • 1
  • 8
  • 1
    Nope, protocols cannot give you multiple inheritance. Especially when both implementations are trying to override the same method. – Sulthan Jan 28 '16 at 11:50
  • @Sulthan, protocols can give you a glimpse of multiple inheritance. In case of having 2 default implementations for same method required in 2 different protocols, the compiler will complain that you are not conforming to the protocol you conformed to last, and will require you to give your own implementation for the function to conform to both protocols. I believe subclassing here is not a good design. – ysholqamy Jan 28 '16 at 12:36
  • The problem is that protocols are not suitable for this exact case. It wouldn't work at all. – Sulthan Jan 28 '16 at 12:43
  • @Sulthan I think protocols are suitable for this case. I cannot see what is wrong with using protocols here, an example of the damage induced by the protocols would be handy to elaborate. – ysholqamy Jan 28 '16 at 13:13
  • Both implementations have to use the same view hierarchy and override the same methods (e.g. `awakeFromNib`). You cannot override methods from protocols. – Sulthan Jan 28 '16 at 13:18
  • @Sulthan There is a simple workaround for this. let the protocol supply its own version of awakeFromNib with different name and call it inside your awakeFromNib, or even better if both protocols have common logic, use yet another third protocol to encapsulate this logic and make each protocol extend the the third protocol. Concerning the view hierarchy issue, each protocol can specify certain properties which are essential in order for the protocol to work, these properties can be used inside the protocol extension itself. – ysholqamy Jan 28 '16 at 13:43
  • 1
    The critical problem here is that the functionality cannot be separated into two independent components (protocols), the components need to know about each other. That's the core problem. – Sulthan Jan 28 '16 at 13:59
  • Thanks for the effort but I'm not sure if I can use a protocol here. I've explained it in the comment I added at the question. – Laap Jan 28 '16 at 14:19
  • @Laap I am pretty sure there is someway to use a protocol here, but I need to know more about the required features of DeleteItem and OpenDetail. We can chat about it if you want and I will be glad to help if I could. – ysholqamy Jan 31 '16 at 10:03