使用Coordinator设计模式实现ViewController间传参(无需prepareForSegue)
解决方案
你需要给Event枚举增加关联值来承载需要传递的参数,同时在目标控制器中声明接收参数的属性,最后在Coordinator的跳转逻辑里将参数赋值给目标控制器即可,具体实现步骤如下:
步骤1:修改Event枚举,增加关联值
给需要传参的事件绑定对应的参数:
enum Event { // 给点击相册、帖子事件绑定用户id和用户名参数 case didTapAlbums(userId: Int, userName: String) case didTapPosts(userId: Int, userName: String) // 后续其他事件如果需要传参也可以按同样方式添加,比如点击相册cell传相册id case didTapAlbumCell(albumId: Int) case didTapPhotoCell(photo: Photo) case didTapPostCell(postId: Int) }
步骤2:给目标控制器声明接收参数的属性
比如你要跳转到的AlbumTableViewController,需要新增属性接收用户id和用户名:
class AlbumTableViewController: UITableViewController, Coordinating { var coordinator: Coordinator? // 新增两个属性用来接收上游传过来的参数 var userId: Int! var userName: String! // 后续你就可以在viewDidLoad里用userId去请求对应用户的相册数据了 override func viewDidLoad() { super.viewDidLoad() // 示例:用userId拉取相册 albumViewModel.fetchAlbums(userId: userId) { [weak self] _ in self?.tableView.reloadData() } // 也可以用userName设置导航栏标题 self.title = "\(userName)的相册" } }
同理,PostTableViewController也按同样方式添加userId和userName属性即可。
步骤3:修改MainCoordinator的跳转逻辑,给目标控制器赋值参数
在eventOccurred方法的switch分支中,取出枚举的关联值,赋值给目标控制器:
func eventOccurred(with type: Event) { switch type { case .didTapAlbums(let userId, let userName): var albumsTableViewController: UITableViewController & Coordinating = AlbumTableViewController() albumsTableViewController.coordinator = self // 赋值参数 if let albumsVC = albumsTableViewController as? AlbumTableViewController { albumsVC.userId = userId albumsVC.userName = userName } navigationController.pushViewController(albumsTableViewController, animated: true) case .didTapPosts(let userId, let userName): var postsTableViewController: UITableViewController & Coordinating = PostTableViewController() postsTableViewController.coordinator = self // 赋值参数 if let postsVC = postsTableViewController as? PostTableViewController { postsVC.userId = userId postsVC.userName = userName } navigationController.pushViewController(postsTableViewController, animated: true) // 其他需要传参的分支也按同样逻辑处理即可 case .didTapAlbumCell(let albumId): var photoTableViewController: UITableViewController & Coordinating = PhotoTableViewController() photoTableViewController.coordinator = self if let photoVC = photoTableViewController as? PhotoTableViewController { photoVC.albumId = albumId } navigationController.pushViewController(photoTableViewController, animated: true) case .didTapPhotoCell(let photo): var detailsViewController: UIViewController & Coordinating = DetailsViewController() detailsViewController.coordinator = self if let detailVC = detailsViewController as? DetailsViewController { detailVC.photo = photo } navigationController.pushViewController(detailsViewController, animated: true) case .didTapPostCell(let postId): var commentTableViewController: UITableViewController & Coordinating = CommentTableViewController() commentTableViewController.coordinator = self if let commentVC = commentTableViewController as? CommentTableViewController { commentVC.postId = postId } navigationController.pushViewController(commentTableViewController, animated: true) } }
步骤4:修改事件触发的代码,传入参数
修改ChallengeViewController中触发事件的代码,把拿到的userId和name传入枚举:
extension ChallengeViewController: UserTableViewCellDelegate { func didTapAlbums(with userId: Int, by name: String) { // 把参数传入事件 coordinator?.eventOccurred(with: .didTapAlbums(userId: userId, userName: name)) } func didTapPosts(with userId: Int, by name: String) { // 把参数传入事件 coordinator?.eventOccurred(with: .didTapPosts(userId: userId, userName: name)) } }
完成以上修改就可以实现跨控制器参数传递了,其他需要传参的跳转场景都可以按这个模式实现。
内容的提问来源于stack exchange,提问作者vintinhum
相关产品推荐
相关产品推荐

