2016-05-30 122 views
0

我無法重新加載tableView。當我的firebaseService.getAllPosts()方法運行時,它會爲我提供數據庫中的兩個帖子(如預期的那樣)。我可以這樣說,因爲當didSet打印運行時,它會給我正確的計數。但是,因爲我知道tableview是在方法運行之前設置的,我知道我需要重新加載tableview來更新我的數據源中的計數。存在這個問題。我特意將posts變量放在我的班級之外,以便可以從每個班級訪問它。 (如果這不是一個好習慣,請告訴我。)無法重新加載tableView

我在哪裏可以運行tableView.reloadData()以便我的tableView數據源更新並給出正確的可能posts?我試過把FeedController().tableView.reloadData()放在didSet中,我試過把它放在viewDidLoad()中,但這些都沒有工作。我也嘗試添加一個名爲_posts的變量,並將其設置爲posts,並將didSet與中的didSet相加,但這也不起作用。

class FeedController: UIViewController, UITableViewDelegate, UITableViewDataSource { 

    let tableView = UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain) 
    let cellId = "PhotoCell" 
    let textCellId = "TextCell" 
    let firebaseService = FirebaseService.sharedInstance 
    static let sharedFeedInstance = FeedController() 
    var posts = [Post]() { 
    didSet { 
     tableView.reloadData() 
     print(posts.count) 
     } 
    } 



    override func viewDidLoad() { 
     super.viewDidLoad() 

     firebaseService.getAllPosts() 

     tableView.dataSource = self 
     tableView.delegate = self 
     self.view.addSubview(tableView) 

    } 

    // MARK: - Table view data source 

    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     // #warning Incomplete implementation, return the number of sections 
     print("sections: \(posts.count)") 
     return posts.count 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     // #warning Incomplete implementation, return the number of rows 
     return 1 
    } 

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let post:Post? = posts[indexPath.section] 


     if let _ = post?.imageContentName { 
      let photoFeedCell = tableView.dequeueReusableCellWithIdentifier(self.cellId, forIndexPath: indexPath) as? FeedTVCellWithPhoto 
      photoFeedCell?.post = post 
      return photoFeedCell! 
     } 

     let textFeedCell = tableView.dequeueReusableCellWithIdentifier(self.textCellId, forIndexPath: indexPath) as? FeedTVCellText 
     textFeedCell?.post = post 
     return textFeedCell! 
    } 
} 

更新1:從FirebaseService類getAllPosts方法

func getAllPosts() { 
     let postRef = ref.child("posts") 
     postRef.observeSingleEventOfType(.Value, withBlock: { snapshot in 
//   print(snapshot.value) 
      if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] { 
       for snap in snapshots { 
        if let postDictionary = snap.value as? Dictionary<String, AnyObject> { 
         let key = snap.key 
         let post = Post(key: key, dictionary: postDictionary) 
         FeedController.sharedFeedInstance.posts.insert(post, atIndex: 0) 
        } 
       } 
      } 

     }) 
    } 
+0

你的問題是,你需要在屏幕上的視圖控制器的上下文中執行'reloadData'; 'FeedController()。tableView.reloadData()'創建一個'FeedController'的新實例,這沒有幫助。你可以得到你想要的一種方法是從'didSet'發佈一個NSNotification,並讓感興趣的視圖控制器訂閱它。是的,全局變量是一個壞主意。創建一個單例類或創建一個實例並將其傳遞給您的每個視圖控制器 – Paulw11

+0

您需要能夠知道getAllPosts何時結束,然後才能調用reloadData。 getAllPosts如何看起來像? – Cristik

回答

0

實際上,您正在以錯誤的方式處理FeedController的方法和屬性。每次在代碼中使用FeedController()時,應該使用self

以下兩段是關於類和實例方法和屬性的複習。隨意忽略他們,如果它的東西,是已經在你的雷達:

  • 如果一個方法或屬性都屬於一個實例(也就是,它可以從實例的實例會發生變化)你self.propertyself.method()調用它,儘管通常你可以放棄self.,只要它不會造成歧義。

  • 如果一個方法或屬性屬於整個類(因此它被聲明爲static letstatic varstatic func),那麼你將與NameOfTheClass.propertyNameOfTheClass.method()調用它。在你的情況下,你可以稱它爲FeedController.propertyFeedController.method()。即,沒有尾隨括號。在任何情況下,應該謹慎使用類方法和屬性,並且在這種情況下可能不合適。

解決了這個問題後,我們有如何重新加載數據的問題。如果移動postsFeedController(使陣列的實例變量),並添加tableView.reloadData()(不self.)到postsdidSet(),你應該是不錯的,儘管其他無關的代碼味道,其他人都強調,你應該嘗試修復,但這些不應該影響您重新加載數據的能力。

+0

謝謝你的信息。它確實有幫助。這裏是rub,我的firebaseService類需要訪問帖子,以便它可以從數據庫中追加項目(參見更新後的代碼)。從FirebaseService類訪問帖子的最佳方式是什麼? –

+0

我爲這個類創建了一個新的靜態常量並引用它。我假設這是正確的?與此同時,一切編譯,但我仍然沒有得到正確更新的部分。 didSet的帖子正在返回2的計數,但部分數量看起來並不像它正在更新。 –

+0

不需要。現在您將'FeedController'轉換爲單例。這是爲了保持PG13,這是不明智的。單例是一種需要謹慎使用的模式,99%的時間適用於模型層的某些組件;幾乎從不在VC層。 – catalandres

0

所以了蝙蝠:

  • 「FeedController()tableView.reloadData()」 是 實例化另一FeedController。這是行不通的。重新加載呼叫的位置取決於您的要求。例如,如果您在來回切換到此UIViewController並且其他UIViewController中的數據正在更改時發生大量的segues,則可以重載viewWillAppear()或其他生命週期方法。你需要在tableView上調用加載到UIWindow中的UIViewController的實例,而不是你現在正在做的事情。
  • 任何原因爲什麼你編程的方式做了很多這種東西,而不是通過故事板 ?無論哪種方式都很好,但我發現故事板 是一個很好的分離。例如,如果您通過故事板使用了UITableViewController,則可以通過代碼和數據源來設置代理和數據源,而不必通過代碼看起來像醜陋的樣板。只要符合協議,您也可以在不使用UITableViewController的情況下設置它們。那些可以在故事板應該處理的事情應該是,這是我平時經常遇到的事情。
  • 你的類正在擴展UIViewController和實現這兩個協議,爲什麼不擴展一個UITableViewController?除非你手動將UITableView放在那裏,並且需要在UIViewController上顯示除UITableView之外的其他東西,否則我沒有理由去做你正在做的事情。
  • 還有一點需要注意的是,你在做PhotoFeedCell和TextFeedCell的方式有點奇怪,並給出了混合信號。你將出現一個可重用的單元格並且可選地將其投射出來,然後使用可選的鏈接,這兩個都意味着你接受它可能是零,但是之後立即強制解開它。
+0

這不是一個答案 –

+0

我告訴你,實例化另一個FeedController的部分將不起作用,它放在哪裏不是答案? 「我在哪裏可以運行tableView.reloadData(),以便我的tableView數據源更新,並給我正確的帖子?」 「何處放置重載調用將取決於您的要求,例如,如果您在來回UIViewController的地方出現大量的中斷,並且其他UIViewController中的數據正在更改,則可以在重載中重新加載viewWillAppear()或其他生命週期方法。「 – Jay

+0

我已經說過,在我的帖子中,我試過了,並沒有工作。就你說的放哪裏來說,你有一個與此無關的例子。對於這個問題,我並沒有使用segues甚至IB。 –