简体   繁体   English

如何推送不在导航控制器中的视图控制器? 迅速

[英]How do I push a View Controller that's not in a navigation controller? Swift

I have two ViewControllers, TimeZonesTable and ResultsTableController .我有两个 ViewController, TimeZonesTableResultsTableController

TimeZonesTable includes a search bar. TimeZonesTable包括一个搜索栏。 The results of the search are displayed in ResultsTableController .搜索ResultsTableController显示在ResultsTableController

Tapping on a result in ResultsTableController saves the timezone to Core Data and (should) dismiss the ResultsTableController and reload the TimeZonesTable showing all of the saved time zones.点击 ResultsTableController 中的ResultsTableController将时区保存到 Core Data 并且(应该)关闭ResultsTableController并重新加载TimeZonesTable显示所有保存的时区。

I cannot get the TimeZonesTable to reload after dismissing ResultsTableController .关闭ResultsTableController后,我无法重新加载TimeZonesTable

I've tried reloading the TimeZonesTable table in the viewWillDisappear function on ResultsTableController but it's not working.我试着重装TimeZonesTable表中的viewWillDisappear的功能ResultsTableController但它不工作。

Any help would be appreciated.任何帮助,将不胜感激。

Note: ResultsTableController is not in a navigation controller.注意: ResultsTableController不在导航控制器中。

TimeZonesTable时区表

import UIKit
import CoreData

class TimeZonesTable: UITableViewController, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {

    var cities: [Zone] = []
    var savedCities: [SavedCity] = [] {
        didSet {
            refreshData()
        }
    }
    var resultsTableController: ResultsTableController!

    override func viewDidLoad() {

        getSavedCities()
        getAvailableCities()

        navigationItem.leftBarButtonItem = editButtonItem
        navigationItem.leftBarButtonItem?.tintColor = UIColor.label

        resultsTableController = ResultsTableController()

        let searchController = UISearchController(searchResultsController: resultsTableController)

        searchController.searchResultsUpdater = self
        searchController.searchBar.autocapitalizationType = .none

        if #available(iOS 11.0, *) {
            // For iOS 11 and later, place the search bar in the navigation bar.
            navigationItem.searchController = searchController

            // Make the search bar always visible.
            navigationItem.hidesSearchBarWhenScrolling = false
        } else {
            // For iOS 10 and earlier, place the search controller's search bar in the table view's header.
            tableView.tableHeaderView = searchController.searchBar
        }

        searchController.delegate = self
        searchController.searchBar.delegate = self // Monitor when the search button is tapped.
        definesPresentationContext = true

    }

    func getAvailableCities() {

        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        let url = Bundle.main.url(forResource: "data", withExtension: "json")!

        let task = session.dataTask(with: url) { data, response, error in

            // Check for errors
            guard error == nil else {
                print ("error: \(error!)")
                return
            }
            // Check that data has been returned
            guard let content = data else {
                print("No data")
                return
            }

            do {
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                let fetchedData = try decoder.decode([Zone].self, from: content)

                for city in fetchedData {
                    self.cities.append(city)
                }

            } catch let err {
                print("Err", err)
            }
        }
        // Execute the HTTP request
        task.resume()
    }

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return savedCities.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "timeZoneCell") as! TimeZoneCell

        if let city = savedCities[indexPath.row].cityName {

            cell.cityName.text = "\(city)"

            if let date = savedCities[indexPath.row].formattedDate {

                let formatter = DateFormatter()
                formatter.dateFormat = "yyyy-MM-dd"
                let formattedDate = formatter.date(from: date)

                formatter.dateFormat = "EEE, d MMM yyyy"
                let dateString = formatter.string(from: formattedDate!)

                cell.cityDate.text = dateString
            }

            if let time = savedCities[indexPath.row].formattedTime {

                let formatter = DateFormatter()
                formatter.dateFormat = "HH:mm:ss"
                let formattedTime = formatter.date(from: time)

                formatter.dateFormat = "HH:mm"
                let timeString = formatter.string(from: formattedTime!)

                cell.currentCityTime.text = timeString
            }
        }
        return cell
    }

    func updateSearchResults(for searchController: UISearchController) {

        let searchBar = searchController.searchBar
        filterContentForSearchText(searchBar.text!)
    }

    // Filter results based on search text
    func filterContentForSearchText(_ searchText: String) {

        let filteredArray = cities.filter ({$0.cityName?.lowercased().range(of: searchText.lowercased()) != nil})

        resultsTableController.filteredCities = filteredArray
        resultsTableController.tableView.reloadData()
    }

    func getSavedCities() {
        if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
            if let timeZonesFromCD = try? context.fetch(SavedCity.fetchRequest()) {
                if let timeZones = timeZonesFromCD as? [SavedCity] {
                    savedCities = timeZones
                    tableView.reloadData()
                }
            }
        }
    }

    func refreshData() {

        for city in savedCities {

            let config = URLSessionConfiguration.default
            let session = URLSession(configuration: config)
            let originalUrl = "http://vip.timezonedb.com/v2.1/get-time-zone?key=\(apiKey)&format=json&by=city&city=\(city.cityName!)&country=\(city.countryCode!)"

            if let encodedUrl = URL(string: originalUrl.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!) {

                let task = session.dataTask(with: encodedUrl) { data, response, error in

                    // Check for errors
                    guard error == nil else {
                        print ("error: \(error!)")
                        return
                    }
                    // Check that data has been returned
                    guard let content = data else {
                        print("No data")
                        return
                    }

                    do {
                        let decoder = JSONDecoder()
                        decoder.keyDecodingStrategy = .convertFromSnakeCase
                        let fetchedData = try decoder.decode(TimeZones.self, from: content)

                        if let data = fetchedData.zones?.first {

                            DispatchQueue.main.async {

                                // Update time and date
                                city.formatted = data.formatted
                                city.formattedTime = data.formatted!.components(separatedBy: " ").last!
                                city.formattedDate = data.formatted!.components(separatedBy: " ").first!
                                self.tableView.reloadData()

                            }
                        }
                    } catch let err {
                        print("Err", err)
                    }
                }
                // execute the HTTP request
                task.resume()
            }
        }
    }

    @IBAction func refreshButtonTapped(_ sender: Any) {
        getSavedCities()
    }
}

ResultsTableController结果表控制器

import UIKit
import CoreData

class ResultsTableController: UITableViewController {

    var filteredCities = [Zone]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "searchResultsCell")

    }

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return filteredCities.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "searchResultsCell", for: indexPath)

        if let city = filteredCities[indexPath.row].cityName {

            if let country = filteredCities[indexPath.row].countryName {
                cell.textLabel?.text = "\(city.replacingOccurrences(of: "_", with: " ")), \(country)"
            }
        }
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let selectedCity = filteredCities[indexPath.row]

        let config = URLSessionConfiguration.default
        let session = URLSession(configuration: config)
        let originalUrl = "http://vip.timezonedb.com/v2.1/get-time-zone?key=\(apiKey)&format=json&by=city&city=\(selectedCity.cityName!)&country=\(selectedCity.countryCode!)"

        if let encodedUrl = URL(string: originalUrl.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)!) {
            print(encodedUrl)

            let task = session.dataTask(with: encodedUrl) { data, response, error in

                // Check for errors
                guard error == nil else {
                    print ("error: \(error!)")
                    return
                }
                // Check that data has been returned
                guard let content = data else {
                    print("No data")
                    return
                }

                do {
                    let decoder = JSONDecoder()
                    decoder.keyDecodingStrategy = .convertFromSnakeCase
                    let fetchedData = try decoder.decode(TimeZones.self, from: content)

                    if let city = fetchedData.zones?.first {

                        DispatchQueue.main.async {

                            if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {

                                let savedCity = SavedCity(context: context)

                                if let offSet = city.gmtOffset {

                                    savedCity.formattedDate = city.formatted!.components(separatedBy: " ").first!
                                    savedCity.formattedTime = city.formatted!.components(separatedBy: " ").last!
                                    savedCity.formatted = city.formatted
                                    savedCity.countryCode = city.countryCode
                                    savedCity.formattedCityName = city.zoneName!.components(separatedBy: "/").last!
                                    savedCity.countryName = city.countryName
                                    savedCity.gmtOffset = Int32(offSet)
                                    savedCity.zoneName = city.zoneName
                                    savedCity.cityName = city.cityName

                                }
                                // Save to core data
                                (UIApplication.shared.delegate as? AppDelegate)?.saveContext()
                            }
                        }
                    }
                } catch let err {
                    print("Err", err)
                }
            }
            // execute the HTTP request
            task.resume()
            self.dismiss(animated: true, completion: nil)
        }
    }

    override func viewWillDisappear(_ animated: Bool) {
        let vc = TimeZonesTable()
        vc.refreshData()
    }
}

Set a delegate here and add avaibale to it inside ResultsTableController在此设置一个委托,并添加avaibale它里面ResultsTableController

resultsTableController = ResultsTableController() 
resultsTableController.delegate = self

then然后

    // Save to core data
(UIApplication.shared.delegate as? AppDelegate)?.saveContext()
self.delegate?.reload()
 self.dismiss(animated: true, completion: nil)

Since you don't have different functionality in the TimeZoneTable vs the ResultTable i would just do the filter in the TimeZoneTable like this:由于您在 TimeZoneTable 与 ResultTable 中没有不同的功能,因此我只会在 TimeZoneTable 中进行过滤,如下所示:

First add a new var:首先添加一个新的var:

var allCities:[Zone] = []

Then change your getCities to copy the data to the new var然后更改您的 getCities 以将数据复制到新的 var

func getSavedCities() {
    if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
        if let timeZonesFromCD = try? context.fetch(SavedCity.fetchRequest()) {
            if let timeZones = timeZonesFromCD as? [SavedCity] {
                savedCities = timeZones
                allCities = timeZones
                tableView.reloadData()
            }
        }
    }
}

Finally create an IBAction for text change for your SearchTextView最后为您的 SearchTextView 创建一个用于文本更改的 IBAction

@IBAction func searchTextViewChanged(_ sender: Any) {
    savedCities = allCities
    savedCities = savedCities.filter {
        ($0.countryName.lowercased().contains(searchTextView.text) ||
        filterString == "")
    }
    tableView.reloadData()
}

This approach helps you with duplicated code, and you will have less views to manage i don't see what advantage you would get by having 2 almost identical view controllers这种方法可以帮助您处理重复的代码,并且您需要管理的视图更少,我不知道拥有 2 个几乎相同的视图控制器会带来什么好处

Hope this helps even if its not technically exactly what you asked i think is a much cleaner approach to filtering a tableView希望这会有所帮助,即使它在技术上并不完全符合您的要求,我认为这是一种更清洁的过滤 tableView 的方法

You can create protocol and get callback.您可以创建协议并获得回调。 Follow steps and you will get resolved your issue.按照步骤操作,您的问题将得到解决。

Step 1: Create Protocol第 1 步:创建协议

//Step #1
protocol ResultsTableControllerDelegate {
    func didSavedTimeZone()
}

Step 2: Assign delegate第 2 步:分配委托

import UIKit
import CoreData


class TimeZonesTable: UITableViewController, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {
    //Your code
    var resultsTableController: ResultsTableController!

    override func viewDidLoad() {
        // Your code

        resultsTableController = ResultsTableController()

        //Step #2
        resultsTableController.resultsDelegate = self //Asign delegate here

        // Your code

    }
}

*Step 3: Implement delegate in your class and do whatever your needs * *第 3 步:在您的班级中实现委托并做任何您需要的事情 *

//Step #3
extension TimeZonesTable: ResultsTableControllerDelegate {
    func didSavedTimeZone() {
        //Reload your data or Table
    }
}

Step 4: Create delegate in result controller第 4 步:在结果控制器中创建委托

import UIKit
import CoreData

class ResultsTableController: UITableViewController {

    //Step #4
    var resultsDelegate: ResultsTableControllerDelegate?

    //Your code
}

Step 5: Call Delegate after saving the data第五步:保存数据后调用Delegate

Note: Please call delegate before dismiss the controller注意:请在解雇控制器之前致电代表

import UIKit
import CoreData

class ResultsTableController: UITableViewController {

    //Step #4
    var resultsDelegate: ResultsTableControllerDelegate?

    //Your code
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        //Your code
        //Step #5
        resultsDelegate?.didSavedTimeZone()
        self.dismiss(animated: true, completion: nil)
        //Your code
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我如何将视图控制器推到导航控制器 - how could i push view controller to navigation controller 如何以编程方式将下一个视图控制器推入导航控制器? - How can I push the next view controller on a navigation controller programmatically? 使用自定义导航控制器推送过渡时,如何像模式演示文稿一样保留先前的视图控制器? - With a custom navigation controller push transition, how do I have the previous view controller behind like modal presentations? 如何在swift项目中隐藏与导航控制器相连的所有视图控制器的页脚? - how do I hide footer of all view controller witch attach with my navigation controller in swift project? 导航控制器推送视图控制器 - Navigation Controller Push View Controller 如何检查视图控制器是否为初始视图控制器? (SWIFT 3) - How do I check if view controller is initial view controller? (SWIFT 3) 如何通过导航View Controller推送数据 - How to push data through a navigation View Controller Swift-如何将Tab Bar和导航栏添加到单个视图控制器? - Swift-How do I add Tab Bar AND Navigation Bar to a single view controller? 如何使用Swift将文本字段的文本作为下一个导航控制器的标题? - How do I make a text field's text the title of the next navigation controller using Swift? 如何将视图控制器推送到iOS中标签栏中的导航控制器 - how to push a view controller to a navigation controller in a tab bar in iOS
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM