cellForRowAt不使用reloadData()方法调用indexPath

在Swift 3中,我正在尝试创建一个“filter”视图,该视图允许用户按类别和按日期过滤表格视图中的post。 目前,filter视图以模态方式显示,并在您单击“完成”时被取消。

我还没有设置日期/类别function。 首先,我只是想让tableView更新,只显示3个post而不是10 。 为此,我在我的FilterViewController设置destination.numPosts = 3

使用print语句,可以看出TableViewController确实更新了viewDidLoad函数中的posts数组,有3个post。 numberOfRowsInSection被调用并且是正确的。 numberofSections始终返回1 。 在viewDidLoad ,我尝试了self.tableView.reloadData()tableView.reloadData()但是,只在最初运行应用程序时调用cellForRowAt indexPath ,并且在重新加载数据时它不会调用它。

有关如何在FilterViewController被解除时重新填充post表的任何想法?

表视图控制器:

 import UIKit class TableViewController: UITableViewController { let myArray = ["item 1", "item 2", "item 3"] var posts = [Post]() var numPosts = 9 override func viewDidLoad() { super.viewDidLoad() self.tableView.delegate = self self.tableView.dataSource = self // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem() /* let logo = UIImage(named: "860logo.png") let imageView = UIImageView(image:logo) self.navigationItem.titleView = imageView */ var titleView: UIImageView titleView = UIImageView(frame:CGRect(x: 0, y: 0, width: 50, height: 60)) titleView.contentMode = .scaleAspectFit titleView.image = UIImage(named: "860logo.png") self.navigationItem.titleView = titleView //titleView.backgroundColor = UIColor(red:0.18, green:0.20, blue:0.38, alpha:1.0) let newPost = Post(id: 6503, title: "Work Zone Accident", date: "2016-12-05T09:24:47", url: "http://www.mlive.com/news/ann-arbor/index.ssf/2016/12/ann_arbor_brings_charges_again.html", category: "Work Zone Accidents") let newPost2 = Post(id: 6501, title: "Anti-Union Laws (Unemployment)", date: "2016-12-05T09:24:19", url: "http://www.cleveland.com/opinion/index.ssf/2016/12/gop_lawmakers_from_high-jobles.html#incart_river_mobile_home", category: "Anti-Union Laws") let newPost3 = Post(id: 6499, title: "Anti-Union Appointments", date: "2016-12-05T09:23:36", url: "http://prospect.org/article/trump-labor-secretary-could-be-fight-15-worst-nightmare", category: "Anti-Union Laws") let newPost4 = Post(id: 6497, title: "Infrastructure", date: "2016-12-05T09:23:06", url: "http://www.cbpp.org/research/federal-budget/trump-infrastructure-plan-far-less-than-the-claimed-1-trillion-in-new", category: "infrastructure") let newPost5 = Post(id: 6495, title: "Work Zone Accident", date: "2016-12-05T09:22:38", url: "http://www.marinij.com/general-news/20161202/construction-worker-struck-by-car-in-novato", category: "Work Zone Accidents") let newPost6 = Post(id: 6493, title: "Infrastructure", date: "2016-12-05T09:22:03", url: "http://markets.businessinsider.com/news/stocks/There-could-be-an-unexpected-side-effect-of-Trumps-infrastructure-spending-1001554657", category: "infrastructure") let newPost7 = Post(id: 6491, title: "Infrastructure", date: "2016-12-05T09:14:28", url: "http://www.nydailynews.com/opinion/build-not-burn-bridges-infrastructure-article-1.2890434", category: "infrastructure") let newPost8 = Post(id: 6489, title: "Highway Funding", date: "2016-12-01T11:02:55", url: "http://www.gobytrucknews.com/democrats-want-highway-funds/123", category: "Funding") let newPost9 = Post(id: 6487, title: "Highway Funding (Congressional Bottleneck)", date: "2016-12-01T11:02:00", url: "https://www.trucks.com/2016/12/01/raise-fuel-taxes-road-funding-traffic-relief/", category: "Funding") let newPost10 = Post(id: 6485, title: "Highway Funding", date: "2016-12-01T11:01:24", url: "http://www.wsj.com/articles/numbers-dont-add-up-for-trumps-trillion-dollar-building-plan-1480538796", category: "Funding") posts.removeAll() print("Num Posts: \(self.numPosts)") if numPosts >= 0 { posts.append(newPost) } if numPosts >= 1 { posts.append(newPost2) } if numPosts >= 2 { posts.append(newPost3) } if numPosts >= 3 { posts.append(newPost4) } if numPosts >= 4 { posts.append(newPost5) } if numPosts >= 5 { posts.append(newPost6) } if numPosts >= 6 { posts.append(newPost7) } if numPosts >= 7 { posts.append(newPost8) } if numPosts >= 8 { posts.append(newPost9) } if numPosts >= 9 { posts.append(newPost10) } print("Posts Count: \(posts.count)") self.tableView.reloadData() tableView.reloadData() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source //Count Number of Sections override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } //Count Number of Rows in Section override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of rows print(posts.count) return posts.count } //Populate Rows with Content override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //DELETE let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let cell:CustomTableCell = self.tableView.dequeueReusableCell(withIdentifier: "Cell") as! CustomTableCell cell.titleLabel?.text = posts[indexPath.item].title //Format Date String, Set Cell's Date Text let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" let stringDate = dateFormatter.string(from:posts[indexPath.item].date) let dateYear = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:0)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:1)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:2)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:3)])" let dateMonthNumber = Int("\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:5)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:6)])") var dateMonth = "" if dateMonthNumber == 01 { dateMonth = "January" } else if dateMonthNumber == 02 {dateMonth = "February" } else if dateMonthNumber == 03 {dateMonth = "March" } else if dateMonthNumber == 04 {dateMonth = "April" } else if dateMonthNumber == 05 {dateMonth = "May" } else if dateMonthNumber == 06 {dateMonth = "June" } else if dateMonthNumber == 07 {dateMonth = "July" } else if dateMonthNumber == 08 {dateMonth = "August" } else if dateMonthNumber == 09 {dateMonth = "September" } else if dateMonthNumber == 10 {dateMonth = "October" } else if dateMonthNumber == 11 {dateMonth = "November" } else if dateMonthNumber == 12 {dateMonth = "December" } var dateDay = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:8)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:9)])" //Remove 0 from beginning of first 9 days of month (01 becomes 1, 02 becomes 2, etc.) if dateDay.hasPrefix("0") { dateDay = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:9)])" } //DELETE cell.detailTextLabel?.text = dateMonth + " " + String(dateDay) + ", " + String(dateYear) cell.dateLabel?.text = "Date: " + dateMonth + " " + String(dateDay) + ", " + String(dateYear) //Populate Category cell.categoryLabel?.text = "Category: " + posts[indexPath.item].category print("cell called") return cell } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { //Checks that Web View Segue was Activated if segue.identifier == "webViewSegue" { // Make sure segue destination can be a Web View Controller if let destination = segue.destination as? WebViewController { //Get the Index Path for Clicked Cell (so we know which URL in array to grab), set URL in destination WebViewController let indexPath = self.tableView.indexPathForSelectedRow!.row destination.urlAddress = posts[indexPath].url } } if segue.identifier == "filterSegue" { print("FILTER ACTIVATED") } } } 

过滤视图控制器:

 import UIKit class FilterViewController: UIViewController { @IBAction func cancelAction(_ sender: UIBarButtonItem) { _ = navigationController?.popViewController(animated: true) dismiss(animated: true, completion:nil) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. var titleView: UIImageView titleView = UIImageView(frame:CGRect(x: 0, y: 0, width: 50, height: 60)) titleView.contentMode = .scaleAspectFit titleView.image = UIImage(named: "860logo.png") self.navigationItem.titleView = titleView } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { //Checks that Web View Segue was Activated if segue.identifier == "setFilterSegue" { // Make sure segue destination can be a Web View Controller if let destination = segue.destination as? TableViewController { //Get the Index Path for Clicked Cell (so we know which URL in array to grab), set URL in destination WebViewController destination.numPosts = 3 destination.tableView.reloadData() _ = navigationController?.popViewController(animated: true) dismiss(animated: true, completion:nil) } } } } 

您必须手动调用tableView.reloadData()。 目前,您只在viewDidLoad()中调用它,这意味着只有在加载视图时才会调用它。

如果要修改另一个视图中的数据(并且尚未卸载视图),另一个想法是在viewDidAppear()中调用它。

viewDidLoad仅在最初加载视图时被调用一次(例如,从故事板中)

如果您希望每次显示视图时都要发生某些事情,请使用viewWillAppear或viewDidAppear。

以下两行代码执行相同的操作:

 self.tableView.reloadData() tableView.reloadData() 

注意:必须在主线程上调用tableView.reloadData。 您可能必须按如下方式将调用包装到reloadData:

 // for Swift 3 DispatchQueue.main.async { self.tableView.reloadData() } 
  • 首先,这两行是多余的:

     self.tableView.reloadData() tableView.reloadData() 

    删除第一个。

  • 其次,移动该行以将表视图重新加载到viewWillAppear 。 与viewDidLoad不同, viewDidLoad仅在每次要显示视图时多次调用viewWillAppear调用。

     override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) tableView.reloadData() } 

最后,你创建日期字符串的方式真的很可怕。 有一个更方便的方式。

更换

 //Format Date String, Set Cell's Date Text let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" let stringDate = dateFormatter.string(from:posts[indexPath.item].date) let dateYear = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:0)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:1)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:2)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:3)])" let dateMonthNumber = Int("\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:5)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:6)])") var dateMonth = "" if dateMonthNumber == 01 { dateMonth = "January" } else if dateMonthNumber == 02 {dateMonth = "February" } else if dateMonthNumber == 03 {dateMonth = "March" } else if dateMonthNumber == 04 {dateMonth = "April" } else if dateMonthNumber == 05 {dateMonth = "May" } else if dateMonthNumber == 06 {dateMonth = "June" } else if dateMonthNumber == 07 {dateMonth = "July" } else if dateMonthNumber == 08 {dateMonth = "August" } else if dateMonthNumber == 09 {dateMonth = "September" } else if dateMonthNumber == 10 {dateMonth = "October" } else if dateMonthNumber == 11 {dateMonth = "November" } else if dateMonthNumber == 12 {dateMonth = "December" } var dateDay = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:8)])\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:9)])" //Remove 0 from beginning of first 9 days of month (01 becomes 1, 02 becomes 2, etc.) if dateDay.hasPrefix("0") { dateDay = "\(stringDate[stringDate.index(stringDate.startIndex, offsetBy:9)])" } //DELETE cell.detailTextLabel?.text = dateMonth + " " + String(dateDay) + ", " + String(dateYear) cell.dateLabel?.text = "Date: " + dateMonth + " " + String(dateDay) + ", " + String(dateYear) 

 //Format Date String, Set Cell's Date Text let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" let date = dateFormatter.date(from: posts[indexPath.item].date)! dateFormatter.dateFormat = "MMMM d, yyyy" cell.dateLabel?.text = "Date: " + dateFormatter.string(from:date)