提问者:小点点

如何在延迟后加载容器视图控制器:Swift


我一直在做一个应用程序。 我是一个初学者,所以请忽略任何错误。

问题是我有一个视图控制器,它有2个容器视图控制器,由一个分段控件控制。

在此处输入图像说明

他们三个都有各自的类:(比方说)

  1. MainViewController
  2. FirstViewController
  3. SecondViewController

在main view controller中,我从firebase获取一些数据,我将这些数据存储在一个数组中,这个数组将被传递给第一个和第二个容器视图,这两个容器视图有它们的表视图,这些表视图将基于传递的数组加载数据。

现在,在数据返回MainViewController之前,第一个和第二个视图控制器已经传递了一个空数组,并且没有数据加载到它们的表视图中(显然是因为数组是空的)。

我希望容器视图控制器在收到数据并加载数组之后加载。 有什么需要帮忙的吗?谢谢

另外,我不执行任何segue,因为这些是容器视图,它们作为主视图容器加载自动加载。

编辑:使用原始代码更加精确和清晰:最初我有3个视图控制器

  1. SearchResultsScreenViewController(主VC)
  2. GuidesListSearchScreenViewController(第一个容器VC)
  3. ServicesListSearchScreenViewController(第二个容器VC)

在主VC中,我使用了一个分段控件来查看屏幕上的容器VC,如下所示:

import UIKit
import Firebase

class SearchResultsScreenViewController: UIViewController
{
    
    @IBOutlet weak var GuideListView: UIView!
    @IBOutlet weak var ServicesListView: UIView!
    
    var searchQueryKeyword: String?
    var guidesDataArray = [GuideDM]()
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        ServicesListView.isHidden = true
        populateGuidesList()
    }
   
    
    @IBAction func SegmentChanged(_ sender: UISegmentedControl)
    {
        switch sender.selectedSegmentIndex
            {
            case 0:
                GuideListView.isHidden = false
                ServicesListView.isHidden = true
                break
            case 1:
                GuideListView.isHidden = true
                ServicesListView.isHidden = false
                break
            default:
                break
            }
    }
    
    func populateGuidesList()
    {
        let dbRef = Firestore.firestore().collection("guide")
        dbRef.getDocuments
        { (snapshot, error) in
            if let err = error
            {
                print(err.localizedDescription)
                print("Error: Unable to find guides list")
            }
            else
            {
                if let snap = snapshot
                {
                    print("List is started now")
                    for doc in snap.documents
                    {
                        if doc.exists
                        {
                            let data = doc.data()
                            let city = data["city"] as? String ?? ""
                            let province = data["province"] as? String ?? ""
                            let country = data["country"] as? String ?? ""
                            if city.localizedCaseInsensitiveContains(self.searchQueryKeyword!) || province.localizedCaseInsensitiveContains(self.searchQueryKeyword!) || country.localizedCaseInsensitiveContains(self.searchQueryKeyword!)
                            {
                                let guideId = doc.documentID
                                let guideEmail = data["email"] as? String ?? ""
                                let name = data["name"] as? String ?? ""
                                let dob = data["dob"] as? String ?? ""
                                let feeCurrency = data["feeCurrency"] as? String ?? ""
                                let status = data["status"] as? String ?? ""
                                let totalReviews = data["totalReviews"] as? Int ?? 0
                                let rating = data["rating"] as? Int ?? 0
                                let baseFee = data["baseFee"] as? Int ?? 0
                                let isGuideFeatured = data["isGuideFeatured"] as? Bool ?? false

                                //make a model of guide and append in array
                                let guide = GuideDM(id: guideId, email: guideEmail, name: name, dob: dob, city: city, province: province, country: country, feeCurrency: feeCurrency, status: status, baseFee: baseFee, rating: rating, totalReviews: totalReviews, isGuideFeatured: isGuideFeatured)
                                self.guidesDataArray.append(guide)
                            }
                        }
                    }
                    print("list is finalized now")
                }
            }
        }
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
        
       if segue.identifier == "searchScreentoGuideListSegment"
       {
           let guidesListContainerVC = segue.destination as! GuidesListSearchScreenViewController
           guidesListContainerVC.guidesDataArray = self.guidesDataArray
       }
        
    }

}

在上面的类中,我的代码调用函数“populateGuidesList()”,该函数进行网络调用以获取数据,同时加载我的容器视图。 问题是,在网络调用返回数据之前,空数组会被传递给我的“GuidesListSearchScreenViewController”,即(第一个容器VC),它是一个表视图,并加载一个空表,因为数组尚未填充。

我的第一堂容器VC课:

import UIKit
import Firebase

class GuidesListSearchScreenViewController: UIViewController
{

    @IBOutlet weak var guidesListTableView: UITableView!
    var guidesDataArray = [GuideDM]()
    
    override func viewDidLoad()
    {
        super.viewDidLoad()

        guidesListTableView.delegate = self
        guidesListTableView.dataSource = self
        
        guidesListTableView.register(UINib(nibName: "GuidesListCellSearchScreenTableViewCell", bundle: nil), forCellReuseIdentifier: "guidesListCell")
    }
    
}


extension GuidesListSearchScreenViewController: UITableViewDataSource, UITableViewDelegate
{
    
    // below functions are to setup the table view
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return guidesDataArray.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = guidesListTableView.dequeueReusableCell(withIdentifier: "guidesListCell") as! GuidesListCellSearchScreenTableViewCell
        //adding properties to cell and then returning cell
        return cell
    }
    
}

目标:要么在数组中接收到数据后加载容器视图,要么通过再次将数组传递给容器VC并重新加载表来刷新表。

其他解决方案:我曾尝试在第一个容器VC类中加载所有这些数组数据,然后从那里重新加载表视图数据,这工作得非常好,但对我来说这是一个非常低效的方法,因为我在两个容器视图中都需要这个数组,所以为每个容器VC进行网络调用似乎非常低效。 因此,我尝试一次获取数据,并传入两个容器视图。 如果你觉得我错了,请纠正我。

另外,我已经删除了其他功能并简化了代码。 我们将非常感谢您的帮助。


共2个答案

匿名用户

我只能在没有看到代码的情况下推测,所以这里什么都没有。。。 这是一个非常重要的问题

尝试在MainViewController的viewDidLoad()上执行以下操作:

>

  • 使用与FirstViewController相关的属性(为了便于解释,我们假设它名为'first VC')。 您要做的是转到,firstvc.view.IsHidden=true

    对SecondViewController执行相同操作。

    为什么? 这样做将从MainViewController的视图中隐藏容器VC的(ViewController)。

    这将使它返回查看,您获取的数据已经填充了它。

    希望这能帮到你。

  • 匿名用户

    容器视图控制器将在主视图控制器加载时加载。 因此,当主视图控制器接收到数据时,您必须更新容器视图控制器。

    一种简单的方法是更新容器视图控制器中的数组,并在数组上使用didset强制容器视图控制器重新加载自己。

    例如,如果FirstViewController在表视图中显示数组数据,则可以执行以下操作:

    var array: [ArrayItem] {
        didSet {
            tableView.reloadData()
        }
    }
    

    然后在主视图控制器中,当接收到数据时,设置此属性:

    getData() { resultArray in 
        firstViewController.array = resultArray
    }
    

    请注意,由于您没有提供任何代码,这些只是示例,您将不得不调整它们以适合您的具体情况。

    编辑:根据下面的注释,您应该注意不要在FirstViewController的视图加载之前设置该数组,否则对TableView.ReloadData()的调用将导致应用程序崩溃。