协议与子类

时间:2018-08-21 00:39:00

标签: swift protocols subclass

我想创建一个协议Pannable,以便可以将其添加到现有单元格中以便进行平移:

@objc protocol Pannable {
    var panGesture: UIPanGestureRecognizer { get }

    var margin: CGPoint { get }

    var limitLeft: CGFloat { get set }
    var limitRight: CGFloat { get set }

    var shadowOn: Bool { get set }

    var background: UIView { get set }
    var shadowView: UIView { get set }

    var enablePanR: Bool { get set }
    var enablePanL: Bool { get set }

    func handlePan(_ recognizer: UIPanGestureRecognizer)
}

extension Pannable where Self: UITableViewCell {

    var original: CGFloat { return background.frame.minX }

    func handlePan(_ recognizer: UIPanGestureRecognizer) {
        // pan cell
    }

    func configureLayout() {
        contentView.layer.cornerRadius = background.layer.cornerRadius
        let size = shadowOn ? shadowView.layer.shadowOffset.height : 0

        let height = bounds.height - margin.y - size
        let widths = bounds.width - margin.x * 2

        let rect = CGRect(x: margin.x, y: size, width: widths, height: height)

        background.frame = rect
        contentView.frame = rect

        shadowView.layer.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: background.layer.cornerRadius).cgPath
    }

    func setup() {
        insertSubview(background, at: 0)
        insertSubview(shadowView, at: 0)

        background.clipsToBounds = true

        panGesture.addTarget(self, action: #selector(handlePan))
        panGesture.delegate = self

        addGestureRecognizer(panGesture)
    }

    func reset() {
        contentView.frame.origin.x = original
    }

    func enableShadow() {
        shadowView.layer.shadowOffset = CGSize(width: 2, height: 2)
        shadowView.layer.shadowRadius = 2
        shadowView.layer.shadowOpacity = 0.5
        shadowView.layer.shadowColor = UIColor.black.cgColor

        shadowOn = true
    }
}

要使用此Pannable,我必须将setup()configureLayout()添加到单元格的初始化程序和layoutSubviews()

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    setup()
}

override func layoutSubviews() {
    super.layoutSubviews()

    configureLayout()
}

但是,这意味着我也可以将UITableViewCell子类化并直接添加它而不是创建协议。是否可以使用协议并使用适当的初始化程序/ layoutSubviews扩展符合协议的UITableViewCell

1 个答案:

答案 0 :(得分:1)

您的问题比问题提出的要深。您肯定已经(从编译器的尖叫声中)注意到这是行不通的:

extension Pannable where Self: UITableViewCell {
    func handlePan(_ recognizer: UIPanGestureRecognizer) {
        // pan cell
    }
    func setup() {
        panGesture.addTarget(self, action: #selector(handlePan))
    }
}

协议扩展是Swift的功能。 Objective-C无法看到它。但是选择器是Objective-C的功能。因此它看不到Swift协议扩展中声明的函数。

基本上,尝试使用协议扩展将功能注入到Objective-C本身将以某种方式自动调用的Objective-C类中,这注定是失败的项目。正是由于这个原因,在这里,子类将变得更加有意义。