Как программно представить контроллер представления из UIVIew

Я использую класс, который является подклассом 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 ответов

Сначала получить верх 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)
}

.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)

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

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

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

  • Ваш MyClass представление имеет только код презентации
  • Вы должны иметь ViewController, который имеет ссылку на это MyClass Посмотреть
  • Этот ViewController имеет @IBAction func tryAgainButtonPressed
  • Оттуда вы можете представить следующий 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
    UIApplication.shared.keyWindow?.rootViewController?.present(newViewController, animated: true, completion: nil)
}

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

open override func awakeFromNib() {

}

}

Извините за задержку с ответом. 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)

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

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

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)
    }

}

Вы можете достичь этого двумя способами

  • протокол
  • Дав ссылку на этот контроллер представления на представление при инициализации представления
Другие вопросы по тегам