4

Is it possible to inherit a class depending on the version of iOS?

I have the code:

let cell1 = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier1", for: indexPath) as! MyCell1
// ....
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier2", for: indexPath) as! MyCell2

It is necessary for me that for the iOS version <11.0 used class with third-party framework, but in the iOS version> = 11.0 was used standard solution.

class MyCell1: BaseTableViewCell {
    // Different code
}

class MyCell2: BaseTableViewCell {
    // Different code
}

// Available for iOS >= 11.0
class BaseTableViewCell: UITableViewCell {
}

// Available for all other versions
class BaseTableViewCell: SwipeTableViewCell {
}

In the third-party framework I have this class:

class SwipeTableViewCell: UITableViewCell {
    // Different code
}

In substance, I want to add an inter-layer class for iOS < 11.0

Vergiliy
  • 1,248
  • 1
  • 13
  • 22
  • Can you describe the functionality that `SwipeTableViewCell` adds? In particular, does it only add methods, or does it overload methods? – Rob Napier Apr 24 '19 at 12:07
  • 1
    @RobNapier This is a class from the [SwipeCellKit](https://github.com/SwipeCellKit/SwipeCellKit) framework. This class: https://github.com/SwipeCellKit/SwipeCellKit/blob/develop/Source/SwipeTableViewCell.swift – Vergiliy Apr 24 '19 at 12:28

2 Answers2

2

Is it possible to inherit a class depending on the version of iOS?

The base class is established when your code is compiled, not at run time, so you can't switch base classes depending on which OS version your code is running on.

It is necessary for me that for the iOS version <11.0 used class with third-party framework, but in the iOS version> = 11.0 was used standard solution.

The way to do this is to use containment instead of inheritance, so that you can configure your object with the desired behavior when the code runs. Think of it like delegation, where you have a helper object that lets you specialize a class without creating a subclass.

For example, let's say you've got your BaseTableViewCell class defined based on UITableViewCell, as you've shown:

// Available for iOS >= 11.0
class BaseTableViewCell: UITableViewCell {
}

But maybe iOS versions earlier than 11.0 don't have some functionality that you want related to swiping, so you first create a protocol that declares functions that provide behaviors you need to add:

protocol SwipingProtocol {
    func swipe()
}

...and create classes that implement the function(s) in that protocol

class OldSwiper : SwipingProtocol {
    func swipe() { // put your < 11.0 swiping code here }
}

class NewSwiper : SwipingProtocol {
    func swipe() { // put your >= 11.0 swiping code here }
}

...and finally add support for that to your base class:

class BaseTableViewCell: UITableViewCell {
    var swiper : SwipingProtocol

    init() {
        if systemVersion < 11.0 {
            swiper = OldSwiper()
        }
        else {
            swiper = NewSwiper()
        }
    }

    func swipe() {
        swiper.swipe()
    }
}

So now you've got two (or perhaps more) implementations of the swiping behavior contained in OldSwiper and NewSwiper, and your base class decides which one to use depending on the environment it's running in.

You could, of course, skip the whole protocol thing and build both old and new behaviors into BaseTableViewCell, switching between them with if statements in each method where there are OS-dependent customizations. Using a protocol and a helper class is nicer, though, because it keeps all the version-specific stuff contained in separate classes. It also makes your code flexible -- if you want to do something different for iOS 14.0 and greater in the future, making that change is just a matter of creating a new SwipingProtocol implementation.

Caleb
  • 124,013
  • 19
  • 183
  • 272
0

This should have what you need: Check OS version in Swift?

var cell: BaseTableViewCell? = nil

if #available(iOS 11.0, *) {
    cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier1", for: indexPath)
} else {
    cell = tableView.dequeueReusableCell(withIdentifier: "cellIdentifier2", for: indexPath)
}
Jack Hopkins
  • 422
  • 3
  • 14
  • This is not exactly what I need, since in this case, for each `cellN` I need to create two classes (with and without a framework) and there may be more than 20 such cells in the entire application. – Vergiliy Apr 24 '19 at 11:20
  • I'm not 100% sure I understand your question so I probably won't be that helpful but you can't change inheritance at run time. I think the best solution would be to create a protocol that both classes inherit from, however the short answer to your question is no. – Jack Hopkins Apr 24 '19 at 11:28