Как программно представить контроллер представления из UIVIew - PullRequest
0 голосов
/ 07 мая 2018

Я использую класс, который является подклассом MessageView ( Swift Message Library ), который наследуется от UIView. Внутри у меня есть UIButton, и я хочу программно представить еще один ViewController через него.

Вот мой код ниже:

import Foundation
import SwiftMessages
import UIKit

class MyClass: MessageView {

    var hideBanner: (() -> Void)?


    @IBAction func helpButtonPressed(_ sender: UIButton) {
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
        self.present(newViewController, animated: true, completion: nil)

    @IBAction func tryAgainButtonPressed(_ sender: UIButton) {
        hideBanner?()
    }

    open override func awakeFromNib() {

    }

}

Я пробовал это, но он не работает, так как UIView не имеет настоящего метода.

Ответы [ 7 ]

0 голосов
/ 07 мая 2018

Этого можно достичь двумя способами

  • Протокол
  • При указании ссылки этого контроллера представления на представление при инициализации представления
0 голосов
/ 24 мая 2018

Извините за поздний ответ. MessageView уже предоставляет buttonTapHandler обратный вызов для вас:

/// An optional button tap handler. The `button` is automatically
/// configured to call this tap handler on `.TouchUpInside`.
open var buttonTapHandler: ((_ button: UIButton) -> Void)?

@objc func buttonTapped(_ button: UIButton) {
    buttonTapHandler?(button)
}

/// An optional button. This buttons' `.TouchUpInside` event will automatically
/// invoke the optional `buttonTapHandler`, but its fine to add other target
/// action handlers can be added.
@IBOutlet open var button: UIButton? {
    didSet {
        if let old = oldValue {
            old.removeTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)
        }
        if let button = button {
            button.addTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)
        }
    }
}

, который автоматически вызывается для любой кнопки, подключенной к розетке button. Поэтому рекомендуемый метод представления другого контроллера представления состоит в том, чтобы заставить контроллер представления настроить логику представления в этом обратном вызове:

messageView.tapHandler = { [weak self] in
    guard let strongSelf = self else { return }
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
    strongSelf.present(newViewController, animated: true, completion: nil)
}

Если ваше представление имеет более одной кнопки, вы можете обработать их все через buttonTapHandler, поскольку он принимает аргумент button. Вам просто нужно настроить механизм целевого действия для каждой кнопки:

otherButton.addTarget(self, action: #selector(MessageView.buttonTapped(_:)), for: .touchUpInside)

Или вы можете добавить один обратный вызов для каждой кнопки, продублировав вышеуказанный шаблон.

0 голосов
/ 07 мая 2018

Вот пример кода с использованием шаблона делегирования.

class YourViewController: UIViewController {
  var yourView: MyClass // may be outlet

    override func viewDidLoad() {
        super.viewDidLoad()

        yourView.delegate = self
    }

}

protocol MyClassDelegate:class {
    func tryAgainButtonDidPressed(sender: UIButton)
}

class MyClass: MessageView {

  weak var delegate: MyClassDelegate?


   @IBAction func tryAgainButtonPressed(_ sender: UIButton) {
        delegate?.tryAgainButtonDidPressed(sender: sender)
    }

}
0 голосов
/ 07 мая 2018

Попробуйте этот # простой код.

import Foundation
import SwiftMessages
import UIKit

class MyClass: MessageView {

var hideBanner: (() -> Void)?


@IBAction func helpButtonPressed(_ sender: UIButton) {
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
    UIApplication.shared.keyWindow?.rootViewController?.present(newViewController, animated: true, completion: nil)
}

@IBAction func tryAgainButtonPressed(_ sender: UIButton) {
    hideBanner?()
}

open override func awakeFromNib() {

}

}
0 голосов
/ 07 мая 2018

Соглашение iOS гласит, что только ViewController s представляет другой ViewController.

Так что ответы выше - где View находит текущий ViewController через UIApplication.sharedApplication().keyWindow?.... , будет работать , но это очень анти-паттерн.

Предпочтительным способом будет:

  • Ваш MyClass просмотр имеет только код презентации
  • У вас должен быть ViewController, который имеет ссылку на этот MyClass view
  • Этот ViewController имеет @IBAction func tryAgainButtonPressed
  • Оттуда вы можете представить следующий ViewController
0 голосов
/ 07 мая 2018

Сначала получите top ViewController, используя это. Тогда вы можете представить свой viewController.

if var topController = UIApplication.sharedApplication().keyWindow?.rootViewController {
    while let presentedViewController = topController.presentedViewController {
        topController = presentedViewController
    }

    // topController now can use for present.
    let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
    topController.present(newViewController, animated: true, completion: nil)
}
0 голосов
/ 07 мая 2018

.present - это метод в UIViewController классе, поэтому вы не можете представить контроллер вида из UIView класса.

Для этого получите контроллер корневого представления и представьте контроллер следующим образом:

let appDelegate  = UIApplication.shared.delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! YourViewController
let storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let newViewController = storyBoard.instantiateViewController(withIdentifier: "newViewController") as! NewViewController
        viewController .present(newViewController, animated: true, completion: nil)
...