无法重新加载tableView

时间:2016-05-30 22:11:35

标签: ios swift uitableview

我无法重新加载tableView。当我的firebaseService.getAllPosts()方法运行时,它会给我数据库中的两个帖子(按预期)。我可以这样说,因为当didSet打印运行时,它会给我正确的计数。但是,因为我知道在方法运行之前设置了tableview,所以我知道我需要重新加载tableview来更新数据源中的计数。这就是问题所在。我故意将posts变量放在我的类之外,因此可以从每个类访问它。 (如果这不是一个好习惯,请告诉我。)

我可以在哪里运行tableView.reloadData(),以便我的tableView数据源更新并为我提供正确的posts?我已尝试将FeedController().tableView.reloadData()放入didSet中,并且我已尝试将其放入viewDidLoad()但这些都不起作用。我还尝试添加一个名为_posts的变量,并将其设置为posts,并将didSet添加到tableView.reloadData()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)
                    }
                }
            }

        })
    }

2 个答案:

答案 0 :(得分:0)

太棒了:

  • “FeedController()。tableView.reloadData()”是 实例化另一个FeedController。那不行。重新加载呼叫的位置取决于您的要求。例如,如果您在此UIViewController中来回转换并且在其他UIViewControllers中更改了数据时发生了很多segue,则可以重新加载viewWillAppear()或其他生命周期方法。你需要在tableView上调用加载到UIWindow中的UIViewController实例,而不是你现在正在做什么。
  • 你以编程方式做很多这样的事情的原因 而不是通过故事板?无论哪种方式都很好,但我找到了故事板 是一个很好的分离。例如,如果您通过故事板使用UITableViewController,则可以让它设置委托和dataSource,而无需通过代码看起来像丑陋的样板。只要符合协议,您也可以在不使用UITableViewController的情况下设置它们。那些可以在故事板中处理的东西应该是我经常去的地方。
  • 您的类正在扩展UIViewController并实现这两个协议,为什么不只是扩展UITableViewController?除非你手动在那里放置一个UITableView,并且需要在UIViewController上显示除UITableView以外的东西,否则我没有理由去做你正在做的事情。
  • 需要注意的是,你正在进行PhotoFeedCell和TextFeedCell的方式有点奇怪并且会产生混合信号。你可以将一个可重复使用的单元格出列并可选地进行铸造,然后使用可选的链接,这两个都意味着你接受它可能是零,但随后强制将其展开。

答案 1 :(得分:0)

从本质上讲,您正在以错误的方式解决FeedController的方法和属性。每次在代码中使用FeedController()时,都应该使用self

以下两段是关于类和实例方法和属性的复习。如果它已经在您的雷达中,请随意忽略它们:

  • 如果某个方法或属性属于某个实例(也就是说,它可能因实例而异),您可以使用self.propertyself.method()来调用它,但通常可以删除{ {1}}只要它不会造成歧义。

  • 如果方法或属性属于整个类(因此它被声明为self.static letstatic var),那么您可以使用{{1 }或static func。在您的情况下,您可以将其称为NameOfTheClass.propertyNameOfTheClass.method()。也就是说,没有尾随括号。在任何情况下,都应该谨慎使用类方法和属性,在这种情况下可能不合适。

解决了这个问题后,我们遇到了如何重新加载数据的问题。如果您在FeedController.property内移动FeedController.method()(使数组成为实例变量)并将posts(不包含FeedController)添加到tableView.reloadData() self.你应该很好,尽管有其他不相关的代码气味,其他人已经强调,你应该尝试修复,但这些不应该影响你重新加载数据的能力。