ios - 协议委托不调用
问题描述
我是 Swift UIKit 的新手,并尝试使用 VIPER 架构制作应用程序。我试图根据这个主题制作它,但我无法从视图中调用演示者函数。这是我的 ViewController 代码
class PokemonViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
presenter?.viewDidLoad()
}
@objc func refresh() {
presenter?.refresh()
}
var presenter: ViewToPresenterPokemonsProtocol?
let reuseIdentifier = "cell"
lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewLayout.init())
collectionView.dataSource = self
collectionView.delegate = self
return collectionView
}()
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Refreshing")
refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
return refreshControl
}()
}
extension PokemonViewController: PresenterToViewPokemonsProtocol {
func onFetchPokemonsSuccess() {
self.collectionView.reloadData()
self.refreshControl.endRefreshing()
}
func onFetchPokemonsFailure(error: String) {
print("View receives the response from Presenter with error: \(error)")
self.refreshControl.endRefreshing()
}
}
还有我的演示者代码
class PokemonPresenter : ViewToPresenterPokemonsProtocol {
weak var view: PresenterToViewPokemonsProtocol?
var interactor: PresenterToInteractorPokemonsProtocol?
var router: PresenterToRouterPokemonsProtocol?
var pokemons: [Pokemon]?
func viewDidLoad() {
print("Presenter is being notified that View was loaded.")
interactor?.loadPokemons()
}
func refresh() {
print("Presenter is being notified that the View was refreshed.")
interactor?.loadPokemons()
}
}
extension PokemonPresenter: InteractorToPresenterPokemonsProtocol {
func fetchPokemonsSuccess(pokemons: [Pokemon]) {
print("Presenter receives the result from Interactor after it's done its job.")
self.pokemons = pokemons
view?.onFetchPokemonsSuccess()
}
func fetchPokemonsFailure(error: String) {
print("Presenter receives the result from Interactor after it's done its job.")
view?.onFetchPokemonsFailure(error: "Couldn't fetch pokemons: \(error)")
}
// func getPokemonSuccess(_ pokemon: Pokemon) {
// router?.pushToPokemonDetail(on: view!, with: pokemon)
// }
func getPokemonFailure() {
print("Couldn't retrieve pokemon by index")
}
}
所以我不知道当我调用演示者的 viewDidLoad 时我做错了什么。我的断点在视图调用演示者的 viewDidLoad 时触发,但预设的 viewDidLoad 中的断点不会触发。
解决方案
这是因为您的应用程序中有两个不同的 PokemonViewController 实例——一个是您在模块路由器中创建的,一个来自故事板。
为什么?您正在使用场景委托。因此,这就是窗口所在的位置,也就是故事板自动加载的位置。您需要防止这种情况并手动构建界面 - 在场景委托中,而不是在应用程序委托中。应用委托代码无用;它组装了一个包含 viper 模块的层次结构,但所有这些都被丢弃了,因为应用程序委托window
不是界面的一部分。
解决方案是:
编辑 Info.plist。在 Application Scene Manifest 中,向下钻取 Storyboard Name 并将其删除。
重写场景委托的第一个方法,以便它完成您的应用程序委托所做的工作。
像这样:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: scene)
window?.backgroundColor = .white
window?.rootViewController = PokemonRouter.createModule()
window?.makeKeyAndVisible()
}
推荐阅读
- python-3.x - 我不确定如何减去日期
- marklogic - 使用 -output_uri_replace 选项
- r - 根据字符值查找变量,然后将它们转换为数字
- mat-table - 垫表常用模板未加载
- reactjs - 应用程序的 react-native-fetch-blob
- python - 如何将 Hive(ORC 格式)表转换为 TFRecord 文件并存储在 HDFS 中?
- php - 如何在 CakePHP 中将登录页面初始化为主页
- javascript - 解析对象数组
- excel - 如何让宏仅在达到某个过滤器时才运行
- database - MS-ACCESS:过滤表,然后显示在未绑定的列表框中