ios - 使用选项卡栏从另一个 View 返回时不会调用 View Controller

标签 ios swift uitabbarcontroller

我有一个带有两个 Controller 的简单应用程序,两个 Controller 之间的导航是通过 UITabBarController 进行的。当应用程序启动时,第一次初始化时,一切都按预期工作,但是当我在第一个 VC 中更改某些内容并切换到第二个 VC,然后再次尝试返回到第一个 VC 时 - 它不会出现。

ViewWillAppear() 添加在我的情况下不起作用,因为调试器甚至没有显示 ViewDidLoad()ViewWillAppear() 函数在第一个 VC 中工作。

Thats how its look (CloudApp record)

MainTabBarController代码:

class MainTabBarController: UITabBarController {

  var photosVC: PhotosCollectionViewController!
  var likesVC: LikesCollectionViewController!

  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .white
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    photosVC = PhotosCollectionViewController(collectionViewLayout: WaterfallLayout())
    likesVC = LikesCollectionViewController(collectionViewLayout: UICollectionViewFlowLayout())

    viewControllers = [
      generateNavigationController(rootViewController: photosVC, title: "Photos", image: #imageLiteral(resourceName: "photos")),
      generateNavigationController(rootViewController: likesVC, title: "Favourites", image: #imageLiteral(resourceName: "heart"))
    ]
  }

  override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    if (self.selectedViewController?.isKind(of: UINavigationController.self))!
    {
      let nav = self.selectedViewController as! UINavigationController
      nav.popToRootViewController(animated: false)
    }
  }

  private func generateNavigationController(rootViewController: UIViewController, title: String, image: UIImage) -> UIViewController {
    let navigationVC = UINavigationController(rootViewController: rootViewController)
    navigationVC.tabBarItem.title = title
    navigationVC.tabBarItem.image = image
    return navigationVC
  }
}

PhotosCollectionVC 代码:

import UIKit

class PhotosCollectionViewController: UICollectionViewController {

  var networkDataFetcher = NetworkDataFetcher()
  private var timer: Timer?

  private var photos = [UnsplashPhoto]()

  private var selectedImages = [UIImage]()

  //    private let itemsPerRow: CGFloat = 2 // относится к UICollectionViewDelegateFlowLayout
  //    private let sectionInserts = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20) // относится к UICollectionViewDelegateFlowLayout

  private lazy var addBarButtonItem: UIBarButtonItem = {
    return UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addBarButtonTapped))
  }()

  private lazy var actionBarButtonItem: UIBarButtonItem = {
    return UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(actionBarButtonTapped))
  }()

  private var numberOfSelectedPhotos: Int {
    return collectionView.indexPathsForSelectedItems?.count ?? 0
  }

  private let enterSearchTermLabel: UILabel = {
    let label = UILabel()
    label.text = "Please enter search term above..."

    label.textAlignment = .center
    label.font = UIFont.boldSystemFont(ofSize: 20)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
  }()

  private let spinner: UIActivityIndicatorView = {
    let spinner = UIActivityIndicatorView(style: .gray)
    spinner.translatesAutoresizingMaskIntoConstraints = false
    return spinner
  }()

  override func viewDidLoad() {
    super.viewDidLoad()
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    setupNavigationBar()
    setupCollectionView()
    setupSearchBar()
    setupEnterLabel()
    setupSpinner()
  }

  private func undateNavButtonsState() {
    addBarButtonItem.isEnabled = numberOfSelectedPhotos > 0
    actionBarButtonItem.isEnabled = numberOfSelectedPhotos > 0
  }

  func refresh() {
    self.selectedImages.removeAll()
    self.collectionView.selectItem(at: nil, animated: true, scrollPosition: [])
    undateNavButtonsState()
  }

  // MARK: - NavigationItems action

  @objc private func addBarButtonTapped() {
    print(#function)
    let selectedPhotos = collectionView.indexPathsForSelectedItems?.reduce([], { (photosss, indexPath) -> [UnsplashPhoto] in
      var mutablePhotos = photosss
      let photo = photos[indexPath.item]
      mutablePhotos.append(photo)
      return mutablePhotos
    })

    let alertController = UIAlertController(title: "", message: "\(selectedPhotos!.count) фото будут добавлены в альбом", preferredStyle: .alert)
    let add = UIAlertAction(title: "Добавить", style: .default) { (action) in
      let tabbar = self.tabBarController as! MainTabBarController
      let navVC = tabbar.viewControllers?[1] as! UINavigationController
      let likesVC = navVC.topViewController as! LikesCollectionViewController

      likesVC.photos.append(contentsOf: selectedPhotos ?? [])
      likesVC.collectionView.reloadData()

      self.refresh()
    }
    let cancel = UIAlertAction(title: "Отменить", style: .cancel) { (action) in
    }
    alertController.addAction(add)
    alertController.addAction(cancel)
    present(alertController, animated: true)
  }

  @objc private func actionBarButtonTapped(sender: UIBarButtonItem) {
    print(#function)

    let shareController = UIActivityViewController(activityItems: selectedImages, applicationActivities: nil)


    shareController.completionWithItemsHandler = { _, bool, _, _ in
      if bool {
        self.refresh()
      }
    }

    shareController.popoverPresentationController?.barButtonItem = sender
    shareController.popoverPresentationController?.permittedArrowDirections = .any
    present(shareController, animated: true, completion: nil)
  }

  // MARK: - Setup UI Elements

  private func setupCollectionView() {
    collectionView.backgroundColor = .white

    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "CellId")
    collectionView.register(PhotosCell.self, forCellWithReuseIdentifier: PhotosCell.reuseId)

    collectionView.layoutMargins = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
    collectionView.contentInsetAdjustmentBehavior = .automatic
    collectionView.allowsMultipleSelection = true

    if let waterfallLayout = collectionViewLayout as? WaterfallLayout {
      waterfallLayout.delegate = self
    }
  }

  private func setupEnterLabel() {
    collectionView.addSubview(enterSearchTermLabel)
    enterSearchTermLabel.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
    enterSearchTermLabel.topAnchor.constraint(equalTo: collectionView.topAnchor, constant: 50).isActive = true
  }

  private func setupSpinner() {
    view.addSubview(spinner)
    spinner.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
    spinner.centerYAnchor.constraint(equalTo: collectionView.centerYAnchor).isActive = true
  }

  private func setupNavigationBar() {
    let titleLabel = UILabel(text: "PHOTOS", font: .systemFont(ofSize: 15, weight: .medium), textColor: #colorLiteral(red: 0.5019607843, green: 0.4980392157, blue: 0.4980392157, alpha: 1))
    navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: titleLabel)
    navigationItem.rightBarButtonItems = [actionBarButtonItem, addBarButtonItem]
    navigationController?.hidesBarsOnSwipe = true
    actionBarButtonItem.isEnabled = false
    addBarButtonItem.isEnabled = false
  }

  private func setupSearchBar() {
    let seacrhController = UISearchController(searchResultsController: nil)
    navigationItem.searchController = seacrhController
    navigationItem.hidesSearchBarWhenScrolling = false
    seacrhController.hidesNavigationBarDuringPresentation = false
    seacrhController.obscuresBackgroundDuringPresentation = false
    seacrhController.searchBar.delegate = self
  }

  // MARK: - UICollecionViewDataSource, UICollecionViewDelegate

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    enterSearchTermLabel.isHidden = photos.count != 0
    return photos.count
  }


  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PhotosCell.reuseId, for: indexPath) as! PhotosCell
    let unspashPhoto = photos[indexPath.item]
    cell.unsplashPhoto = unspashPhoto
    return cell
  }

  override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    undateNavButtonsState()
    let cell = collectionView.cellForItem(at: indexPath) as! PhotosCell
    guard let image = cell.photoImageView.image else { return }
    selectedImages.append(image)

  }

  override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    undateNavButtonsState()
    let cell = collectionView.cellForItem(at: indexPath) as! PhotosCell
    guard let image = cell.photoImageView.image else { return }
    if let index = selectedImages.firstIndex(of: image) {
      selectedImages.remove(at: index)
    }
  }
}

// MARK: - UISearchBarDelegate

extension PhotosCollectionViewController: UISearchBarDelegate {

  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    print(searchText)
    self.spinner.startAnimating()
    timer?.invalidate()
    timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { (_) in
      self.networkDataFetcher.fetchImages(searchTerm: searchText) { [weak self] (searchResults) in
        guard let fetchedPhotos = searchResults else { return }
        self?.spinner.stopAnimating()
        self?.photos = fetchedPhotos.results
        self?.collectionView.reloadData()
        self?.refresh()
      }
    })
  }
}

// MARK: - WaterfallLayoutDelegate
extension PhotosCollectionViewController: WaterfallLayoutDelegate {
  func waterfallLayout(_ layout: WaterfallLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let photo = photos[indexPath.item]
    return CGSize(width: photo.width, height: photo.height)
  }
}

LikesCollectionVC 代码:

import UIKit

class LikesCollectionViewController: UICollectionViewController {

  var photos = [UnsplashPhoto]()

  private lazy var trashBarButtonItem: UIBarButtonItem = {
    return UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: nil)
  }()

  private let enterSearchTermLabel: UILabel = {
    let label = UILabel()
    label.text = "You haven't add a photos yet"
    label.textAlignment = .center
    label.font = UIFont.boldSystemFont(ofSize: 20)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    collectionView.backgroundColor = .white
    collectionView.register(LikesCollectionViewCell.self, forCellWithReuseIdentifier: LikesCollectionViewCell.reuseId)
    collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.minimumInteritemSpacing = 1
    layout.minimumLineSpacing = 1

    setupEnterLabel()
    setupNavigationBar()

  }

  // MARK: - Setup UI Elements

  private func setupEnterLabel() {
    collectionView.addSubview(enterSearchTermLabel)
    enterSearchTermLabel.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true
    enterSearchTermLabel.topAnchor.constraint(equalTo: collectionView.topAnchor, constant: 50).isActive = true
  }

  private func setupNavigationBar() {
    let titleLabel = UILabel(text: "FAVOURITES", font: .systemFont(ofSize: 15, weight: .medium), textColor: #colorLiteral(red: 0.5, green: 0.5, blue: 0.5, alpha: 1))
    navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView: titleLabel)
    navigationItem.rightBarButtonItem = trashBarButtonItem
    trashBarButtonItem.isEnabled = false
  }

  // MARK: - UICollectionViewDataSource

  override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    enterSearchTermLabel.isHidden = photos.count != 0
    return photos.count
  }

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: LikesCollectionViewCell.reuseId, for: indexPath) as! LikesCollectionViewCell
    let unsplashPhoto = photos[indexPath.item]
    cell.unsplashPhoto = unsplashPhoto
    return cell
  }
}

// MARK: - UICollectionViewDelegateFlowLayout
extension LikesCollectionViewController: UICollectionViewDelegateFlowLayout {

  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = collectionView.frame.width
    return CGSize(width: width/3 - 1, height: width/3 - 1)
  }
}

最佳答案

the navigation between which is carried out through the UITabBarController.

不,那不是你正在做的事情。您的选项卡栏 Controller 不会在两个 View Controller 之间导航。它在两个导航 Controller 之间导航。

这就是问题所在。您无法在 viewDidAppear 中检测到任何内容,因为您的 View Controller 不是选项卡 Controller 切换时出现的内容。出现的是导航 Controller 。

关于ios - 使用选项卡栏从另一个 View 返回时不会调用 View Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59161075/

相关文章:

objective-c - 在UIAlertView上设置延迟

ios - 添加到导航的 UIBarButton 在 iOS 13 上不起作用

ios - 如何识别 UITabBarController 跟随哪个 "relationship"?

iphone - UITabBarController 不显示 tabbarItems 名称

ios - 无法将新设备 UDID 添加到配置文件。为什么?

ios - Xcode 9 更新 Swift,紫色警告

ios - Swift SpriteKit 从图像纹理制作 physicsbody 使我的应用程序速度减慢太多

swift - 如何使用 Branch.io 将自定义图像添加到您的链接?

ios - Realm iOS : how expensive is it to initiate Realm with a bundled db?

iphone - 当我在顶部使用 TabBarController 时在底部显示空白