简体   繁体   中英

In Swift / UIKit, how do you generalize a "base" class of UIView to other view types, given that you can't compose much in the various UIView types

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.

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() {
    // …
  }
}
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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM