我有两个ViewController,TimeZonesTable
和ResultsTableController
。TimeZonesTable
包含一个搜索栏。搜索结果显示在ResultsTableController
中。
在ResultsTableController
中点击结果会将时区保存到Core Data,并且(应该)关闭ResultsTableController
并重新加载TimeZonesTable
,显示所有已保存的时区。
关闭TimeZonesTable
后,我无法重新加载ResultsTableController
。
我试图在TimeZonesTable
的viewWillDisappear
函数中重新加载ResultsTableController
表,但是它不起作用。
任何帮助,将不胜感激。
注意:ResultsTableController
不在导航控制器中。
时区表
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()
}
}
结果表控制器
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()
}
}
最佳答案
由于您在TimeZoneTable和ResultTable中没有不同的功能,因此我将在TimeZoneTable中进行过滤,如下所示:
首先添加一个新的变量:
var allCities:[Zone] = []
然后更改您的getCities以将数据复制到新的变量
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()
}
}
}
}
最后,为您的SearchTextView创建用于文本更改的IBAction
@IBAction func searchTextViewChanged(_ sender: Any) {
savedCities = allCities
savedCities = savedCities.filter {
($0.countryName.lowercased().contains(searchTextView.text) ||
filterString == "")
}
tableView.reloadData()
}
这种方法可以帮助您处理重复的代码,并且您将需要更少的视图来管理,但我看不到拥有两个几乎相同的视图控制器会带来什么好处
希望这会有所帮助,即使它在技术上不完全符合您的要求,我认为这是筛选tableView的更简洁的方法
关于ios - 如何推送不在导航 Controller 中的View Controller? swift ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59363429/