取消ViewController并调用viewDidLoad后,ScrollView无法重新加载

时间:2019-11-14 16:16:51

标签: swift uiviewcontroller uiscrollview protocols

我有一个scrollView,其中包含动态数量的WeatherViewController,每个WeatherViewController显示用户已保存的不同城市的天气数据。用户可以从WeatherViewControllers筛选到CityListViewController。他们可以在其中从列表中添加和删除城市,而在解散CityListViewController后又应从scrollView中添加和删除WeatherViewControllers,这就是我遇到的问题。

目前,我正在使用一种协议,在解散CityListViewController时会在scrollViewController中调用viewDidLoad,这是因为我使用调试器跟踪代码后,应该调用的所有代码都是,而跟踪要创建的viewControllers的变量是更改后仍正确,但是scrollView并未更改。如果我从列表中添加/删除城市,scrollView仍显示与以前相同的数量。

函数func createAndAddWeatherScreen被称为更改和所有更改之后的准确时间,如果我关闭该应用程序并重新打开它,则scrollView然后将显示正确数量的viewControllers。似乎一切正常,只是在关闭cityListController时未重新加载scrollView。

侧注:最初打开应用程序时,scrollView会正确加载,其中UIScrollView中的所有正确WeatherWeatherControllers以及列表中正确的城市。

class ScrollViewController: UIViewController, ScrollReloadProtocol {

func reloadScrollView() {

    self.viewDidLoad()
}

//@IBOutlet var totalScrollView: UIScrollView!
var pages = [ViewController]()
var x = 0
var weatherScreensArray = [SavedCityEntity]()
var weatherScreenStringArray = [String]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var horizString = "H:|[page1(==view)]"

let defaults = UserDefaults.standard

let scrollView: UIScrollView = {
    let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.isPagingEnabled = true
    return scrollView
}()


override func viewDidLoad() {
    super.viewDidLoad()


    scrollView.delegate = self

    view = scrollView


    //userDefaults used to keep track of which screen is which to put different cities on different viewControllers
    defaults.set(0, forKey: "screenNumber")
    //load cities to get number of cities saved
    loadCities()

    var views : [String: UIView] = ["view": view]
    //create all weatherWeatherControllers
    while x <= weatherScreensArray.count {

        pages.append(createAndAddWeatherScreen(number: x))
        weatherScreenStringArray.append("page\(x+1)")
        views["\(weatherScreenStringArray[x])"] = pages[x].view
        let addToHoriz = "[\(weatherScreenStringArray[x])(==view)]"
        horizString.append(addToHoriz)

        x+=1
    }

    horizString.append("|")

    let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[page1(==view)]|", options: [], metrics: nil, views: views)
    let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: horizString, options: [.alignAllTop, .alignAllBottom], metrics: nil, views: views)

    NSLayoutConstraint.activate(verticalConstraints + horizontalConstraints)
}

//Function to create and add weatherViewController
func createAndAddWeatherScreen(number: Int) -> ViewController {

        defaults.set(number, forKey: "screenNumber")

        let story = UIStoryboard(name: "Main", bundle: nil)
        let weatherScreen = story.instantiateViewController(identifier: "View Controller") as! ViewController

        weatherScreen.view.translatesAutoresizingMaskIntoConstraints = false

        scrollView.addSubview(weatherScreen.view)

        addChild(weatherScreen)
        weatherScreen.didMove(toParent: self)

    return weatherScreen
}

1 个答案:

答案 0 :(得分:0)

您的代码存在几个架构问题:

  1. 您不应该手动调用viewDidLoad方法,它很容易提取必要的代码以用于提取和重新加载到自己的方法中,而这不会破坏viewController的生命周期。
  2. 您似乎正在尝试将scrollView用作tableView,它提供了作为免费功能的重装,以及更好的内存管理。
  3. 您可以使用.map()而不是while来手动迭代和创建新数组,高阶函数非常有用。

尽管如此,您实际上无法像使用scrollView那样重新加载tableView。它已经包含了您之前添加的视图,在我看来,就像您一次又一次地堆叠额外的视图一样,可视调试器是否可以调试这种情况。

最后,为了在更新约束后更新视图,您需要调用:

setNeedsLayout()
layoutIfNeeded()

让系统知道您要更新子视图及其布局。