swift - ScrollView 在关闭 ViewController 并调用 viewDidLoad 时不会重新加载
问题描述
我有一个滚动视图,其中包含动态数量的 WeatherViewController,每个都显示用户保存的不同城市的天气数据。用户可以从 WeatherViewControllers 转到 CityListViewController。他们可以在列表中添加和删除城市,而在关闭 CityListViewController 时,又应该从滚动视图中添加和删除 WeatherViewControllers,这就是我遇到问题的地方。
目前,我正在使用协议在关闭 CityListViewController 时调用 scrollViewController 中的 viewDidLoad,因为我使用调试器跟踪代码,所有应该被调用的代码都是,并且跟踪要创建多少 viewControllers 的变量在之后是准确的改变,但是滚动视图没有改变。如果我从列表中添加/删除一个城市,scrollView 仍然显示与以前相同的数量。
func createAndAddWeatherScreen 在更改和所有内容之后被调用的准确次数,如果我关闭应用程序并重新打开它,scrollView 然后显示正确数量的 viewControllers。似乎一切正常,除了在关闭 cityListController 时滚动视图没有重新加载。
旁注:在最初打开应用程序时,滚动视图会正确加载 UIScrollView 中所有正确的 WeatherViewController 以及列表中的正确城市。
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
}
解决方案
您的代码存在几个架构问题:
- 您不应该
viewDidLoad
手动调用该方法,很容易提取必要的代码来获取和重新加载到它自己的方法中,这不会破坏viewController
. - 看起来您正在尝试使用
scrollView
as atableView
,它提供重新加载作为免费功能,以及更好的内存管理。 - 您可以使用
.map()
而不是使用while
手动迭代和创建新数组,高阶函数非常有用。
尽管如此,您实际上无法像 a 那样重新加载scrollView
a tableView
。它已经包含了您之前添加的视图,在我看来,您好像在一遍又一遍地堆叠额外的视图,如果使用可视调试器是这种情况,您可以进行调试。
最后,为了在更新约束后更新视图,您需要调用:
setNeedsLayout()
layoutIfNeeded()
让系统知道您要更新子视图及其布局。