2017-01-03 97 views
0

在Swift 3中,我試圖創建一個「Filter」視圖,它允許用戶按類別和日期篩選表視圖中的帖子。目前,篩選器視圖以模態方式呈現,並在您點擊「完成」時被解除。cellForRowAt indexPath沒有被reloadData()方法調用

我還沒有設置日期/類別的功能呢。首先,我只是試圖讓tableView更新爲只顯示3的帖子,而不是10。爲此,我在FilterViewController中設置了destination.numPosts = 3

使用打印語句,可以看出TableViewController實際上更新了其viewDidLoad函數中的帖子數組以具有3帖子。 numberOfRowsInSection被調用並且是正確的。 numberofSections總是返回1。在viewDidLoad中,我試過self.tableView.reloadData()tableView.reloadData()然而,cellForRowAt indexPath只在最初運行應用程序時被調用,並且當數據是重新加載時不會調用此函數。

關於FilterViewController被解僱時如何重新填充帖子表的任何想法?

表視圖控制器:

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) 
     } 
    } 
} 
} 
+1

'self.tableView.reloadData()''裏面viewDidLoad方法()'這被稱爲一次 –

回答

1

你必須調用tableView.reloadData()手動。目前,您只能在viewDidLoad()中調用它,這意味着只有在加載視圖時纔會調用它。

另一個想法是在viewDidAppear()中調用它,如果您在另一個視圖中修改數據(並且該視圖尚未卸載)。

1

viewDidLoad中,只有當視圖最初加載(例如,從一個Storyboard)

如果你想要的東西發生視圖顯示每次使用viewWillAppear中或viewDidAppear被調用一次。

下面的代碼兩行做同樣的事情:

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

注:tableView.reloadData有在主線程中調用。 您可能需要包裝調用reloadData如下:

所有這兩條線
// for Swift 3 
DispatchQueue.main.async { 
    self.tableView.reloadData() 
} 
1
  • 首先是多餘的:

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

    刪除第一個。

  • 其次移動該行以將表視圖重新加載到viewWillAppear。不像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) 
+0

非常感謝您的寶貴意見。我嘗試了viewWillAppear,但是numPosts沒有從FilterViewController更新。所以destination.numPosts = 3不起作用。在viewWillAppear中,我包含了一個print(numPosts),它仍然在輸出10.所以基本上,cellForRowAt被調用,但是它仍然沒有用三個帖子重新加載表格。 –

+0

'numPosts'不影響顯示多少帖子。您必須更改'posts'中的項目數。 – vadian

+0

再次感謝您,您的回覆非常全面和有幫助。而不是numPosts,我嘗試使用posts數組。在FilterViewController中,我添加了一些代碼來直接更改posts數組。它看起來像這樣:destination.posts.removeAll()。然後我創建3個新帖子並將其添加到數組中。但是,在tableViewController的viewWillAppear函數中,它仍然顯示posts.count爲10.你知道爲什麼這不會更新嗎?奇怪的是viewDidLoad被再次調用,並且它有正確的帖子編號。 viewWillLoad不會。 –