【问题标题】:ScrollView not reloading upon dismissing ViewController and calling viewDidLoadScrollView 在关闭 ViewController 并调用 viewDidLoad 时不会重新加载
【发布时间】:2019-11-14 16:16:51
【问题描述】:

我有一个滚动视图,其中包含动态数量的 WeatherViewController,每个都显示用户保存的不同城市的天气数据。用户可以从 WeatherViewControllers 转到 CityListViewController。他们可以在列表中添加和删除城市,然后在关闭 CityListViewController 时从滚动视图中添加和删除 WeatherViewControllers,这就是我遇到问题的地方。

目前,我正在使用协议在scrollViewController中调用viewDidLoad,因为我使用调试器跟踪代码,所有应该被调用的代码是和跟踪要创建多少viewControllers的变量是更改后准确,但是 scrollView 没有改变。如果我从列表中添加/删除一个城市,scrollView 仍然显示与以前相同的数量。

函数 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
}

【问题讨论】:

    标签: swift uiviewcontroller uiscrollview protocols


    【解决方案1】:

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

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

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

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

    setNeedsLayout()
    layoutIfNeeded()
    

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

    【讨论】:

    • 好的,谢谢您的帮助。我不知道你可以使用这样的 tableView 来创建完整的页面!您能否将我链接到某个地方,我可以看到这样使用的 tableView,以便我可以实现它。 (我正在寻找一个水平滑动功能)像 pageViewController
    • 我也尝试/正在尝试使用 pageViewController 获得相同的结果,使用类似的逻辑并再次使一切正常,但在关闭 cityListController 时无法重新加载 pageViewController
    • 您可以使用 collectionView 轻松创建水平滚动的集合。
    • 关于您的其他问题,很难看到,但可能需要检查的地方是确保通过断点调用 viewDidLoad,以检查您在创建页面时是否已更新数据(尝试简单的打印或断点),并确保最初从 scrollView 中删除所有子视图,例如scrollView.subviews.forEach { $0.removeFromSuperview() }
    猜你喜欢
    • 1970-01-01
    • 2017-11-14
    • 2021-02-27
    • 2020-03-25
    • 2021-05-28
    • 2015-12-08
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    相关资源
    最近更新 更多