Создание многоразового просмотра в Swift и добавление обработчика завершения - PullRequest
0 голосов
/ 11 февраля 2019

Я создал sliderView, добавил UIPanGesture и создал отдельный UIView для обработки этого слайдера.Я хочу иметь возможность вызывать этот SliderView в различных ViewControllers, где он мне нужен, но когда я пытаюсь запустить мой код, ИТ-система падает. Я также хотел бы передать обработчик завершения для обработки событий в ViewCOntrollers, где он мне понадобится.Я пытаюсь проследить за процессом СУХО, создав один UIView и используя его на множественном экране.Ниже мой код до сих пор

class TripView: UIView {

    var shouldSetupConstraints = true
    var startingFrame: CGRect?

    var sliderView: UIView!
    var sliderImage: UIImageView!

    let screenSize = UIScreen.main.bounds

    override init(frame: CGRect){
        super.init(frame: frame)
        swipeFunc()
        sliderView = UIImageView(frame: CGRect.zero)
        sliderView.backgroundColor = UIColor.green

        sliderView.autoSetDimension(.height, toSize: screenSize.width / 6)

        self.addSubview(sliderView)

        sliderImage = UIImageView(frame: CGRect.zero)
        sliderImage.backgroundColor = UIColor.clear
        sliderImage.image = UIImage(named: "icons8-double_right_filled.png")
        sliderImage.contentMode = .scaleAspectFit

        sliderImage.autoSetDimension(.width, toSize: screenSize.width / 6)
        sliderImage.autoSetDimension(.height, toSize: screenSize.width / 6)

        self.addSubview(sliderImage)


    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func updateConstraints() {
        if(shouldSetupConstraints) {

            sliderView.autoPinEdgesToSuperviewSafeArea(with: UIEdgeInsets.zero, excludingEdge: .bottom)
            sliderImage.autoPinEdge(toSuperviewEdge: .left)
            sliderImage.autoPinEdge(.bottom, to: .bottom, of: sliderView, withOffset: 0.0)

            shouldSetupConstraints = false
        }

        super.updateConstraints()
    }
}

extension TripView {

    private func swipeFunc() {

        let swipeGesture = UIPanGestureRecognizer(target: self, action: #selector(acknowledgeSwiped(sender:)))
        sliderImage.addGestureRecognizer(swipeGesture)
        sliderImage.isUserInteractionEnabled = true
        swipeGesture.delegate = self as? UIGestureRecognizerDelegate
    }

    @objc func acknowledgeSwiped(sender: UIPanGestureRecognizer) {
        if let sliderView = sender.view {
            let translation = sender.translation(in: sliderView)
            switch sender.state {
            case .began:
                startingFrame = sliderImage.frame
                fallthrough
            case .changed:
                if let startFrame = startingFrame {

                    var movex = translation.x
                    if movex < -startFrame.origin.x { movex = -startFrame.origin.x }

                    let xMax = sliderView.frame.width - startFrame.origin.x - startFrame.width
                    if movex > xMax {
                        movex = xMax

      // I WANT TO PASS A COMPLETION HANDLER HERE. TO BE ABLE TO HANDLE OTHER     EVENTS IN VIEWCONTROLLERS

                    }

                    var movey = translation.y
                    if movey < -startFrame.origin.y { movey = -startFrame.origin.y }

                    let yMax = sliderView.frame.height - startFrame.origin.y - startFrame.height
                    if movey > yMax {
                        movey = yMax

                    }

                    sliderView.transform = CGAffineTransform(translationX: movex, y: movey)
                }
            default: // .ended and others:
                UIView.animate(withDuration: 0.1, animations: {
                    sliderView.transform = CGAffineTransform.identity
                })
            }
        }
    }

}

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Вы можете добавить обработчик завершения как внутреннюю переменную или передать его в инициализаторе.

Например:

class TripView: UIView {
    typealias Callback = () -> ()
    var callback: Callback

    ...
}

Затем, где вы хотите вызвать обратный вызов, просто вызовите:

callback()

Или вы можете определить делегата

protocol TripViewDelegate {
    func didDoSomething(for view: TripView)
}

class TripView: UIView {
    weak var tripViewDelegate: TripViewDelegate?
    // ...
}

И затем вызвать

tripViewDelegate?.didDoSomething(for: self)
0 голосов
/ 11 февраля 2019

Вы звоните swipeFunc, который обращается к sliderImage до инициализации sliderImage.

Вы должны переместить swipeFunc() в конец вашего init метода.

На самом деле, нет необходимости использовать неявно развернутые опции.Вы можете предотвратить сбои, используя необязательные:

let sliderView: UIView = UIImageView(frame: CGRect.zero)
let sliderImage: UIImageView = UIImageView(frame: CGRect.zero)

Поскольку у вас фактически есть два инициализатора, вам, вероятно, следует инициировать все в обоих:

let sliderView: UIView = UIImageView(frame: CGRect.zero)
let sliderImage: UIImageView = UIImageView(frame: CGRect.zero)

override init(frame: CGRect){
    super.init(frame: frame)

    commonInit()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    commonInit()
}

private func commonInit() {
    sliderView.backgroundColor = UIColor.green
    sliderView.autoSetDimension(.height, toSize: screenSize.width / 6)

    self.addSubview(sliderView)

    sliderImage.backgroundColor = UIColor.clear
    sliderImage.image = UIImage(named: "icons8-double_right_filled.png")
    sliderImage.contentMode = .scaleAspectFit

    sliderImage.autoSetDimension(.width, toSize: screenSize.width / 6)
    sliderImage.autoSetDimension(.height, toSize: screenSize.width / 6)

    self.addSubview(sliderImage)

    swipeFunc()
}

Что касается обратного вызова, простообъявите свойство:

class TripView: UIView {
    var onChange: (() -> Void)?
}

и при каждом вызове изменения:

onChange?()

В вашем контроллере вы можете:

var tripView: TripView = ...
tripView.onChange = {
  // handle the event
}
...