Home > Blockchain >  In Swift / UIKit, how do you generalize a "base" class of UIView to other view types, give
In Swift / UIKit, how do you generalize a "base" class of UIView to other view types, give

Time:02-02

Say I have

class Plastic: UIView, SomeProto {
  override something {
    blah
  }
  override func layoutSubviews() {
    blah
  }
}

I then have various custom views GreenPlastic: Plastic , YellowPlastic: Plastic etc.

I want to do exactly the same thing for stack views.

Currently I use copy-paste engineering:

class PlasticForStackViews: UIStackView, SomeProto {
  //.. copy and paste in the identical code.
  //.. if I edit something in one, edit in both
}

Note that you can't compose (unless I drastically misunderstand something, tell me if I'm wrong) any of the good stuff in the UIView classes, layoutSubviews etc.

(Obviously if the issue at hand is just "adding corners" or such you can usually trivially use an extension).

(Note that this does assume the various issues addressed in the "base class" do apply to both UIView and the other view types, stack view in the example. Obviously you couldn't generalize something specific to, say, an image view, across a "similar base class" for the other view types.)

Is there a solution to this problem?

The problem at hand is completely different from a protocol solution, because, in fact, you can't compose (unless I drastically misunderstand something, tell me if I'm wrong) any of the good stuff in the UIView classes ... layoutSubviews etc.

CodePudding user response:

You say

It's completely different from a protocol

but this is a description of protocol extensions:

many of the features of the various view classes are identical and can be handled identically

If you need "overrides" of default implementations, put the declarations in the protocol definition. Otherwise, don't bother.

protocol PlasticProtocol: UIView {
  func something() -> String
}

// MARK: - internal
extension PlasticProtocol {
  func etc() {
    // …
  }

  func something() -> String {
    "default"
  }

  func variousBringupStuff() {
    // …
  }
}
// MARK: - PlasticProtocol
extension Plastic: PlasticProtocol {
  func something() -> String {
    "override"
  }
}
let plastic = Plastic()
plastic.something() // override
let plasticProtocol: some PlasticProtocol = plastic
plasticProtocol.something() // default

Naming is going to be terrible, when you need to override superclass members. And you'll still need to define the overrides and call super. But that's better than copypasta.

// MARK: - UIView
extension Plastic {
  override func layoutSubviews() {
    plastic_layoutSubviews()
    super.layoutSubviews()
  }
}
// MARK: - UIView
extension PlasticProtocol {
  func plastic_layoutSubviews() {
    // …
  }
}

CodePudding user response:

class PlasticView: UIView, SomeProtocol {
    /// Apply all identical code here
}

class GreenPlasticView: PlasticView {
    /// Automatically inherits code from PlasticView
}

class YellowPlasticView: PlasticView {
    /// Automatically inherits code from PlasticView
}

  • Related