【问题标题】:How to delay a return call in Swift如何在 Swift 中延迟回电
【发布时间】:2016-09-05 06:00:40
【问题描述】:

大家好,我目前正在开发一个在 UITableView 中保存书籍列表的程序。如你所知,TableView 有两种方法,一种是 cellForRowAtIndexPath,另一种是我今天要讲的 numberOfRowsInSection。所以我遇到的问题是我访问我的数据库以获取当前在数据库中的书籍数量,以便返回我在 Book stucts 数组中需要多少索引。所以我有两组,买入和卖出,其中可能有也可能没有任何书籍。

无论如何,我填充了我的数组(一开始是空的),然后我将 books.count 作为 numberOfRowsInSection 返回。问题是我一直返回 0,因为在返回执行后数组被填充。

下面是我的代码。

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    populateArray()
    print("books.count: ",books.count)
    return books.count // KEEPS RETURNING 0 BC IT HASN'T POPULATED YET *ARRRRRRGH*
}

func populateArray(){
    print("started looking")
    var indices = 0

    if divider.selectedSegmentIndex == 0{
        ref.child(school).observeEventType(.Value, withBlock: {     (snapshot) in
            let numSelling = snapshot.value!["numSelling"] as! Int // gets numSelling
            if numSelling  > 0 {
                self.noEntries = false
                print("numSelling: ", numSelling) //see console
                indices = numSelling
            }else{
                self.noEntries = true
                indices = 1
                print("No Values Selling")
            }
        }) { (error) in
            print(error.localizedDescription)
        }
    }else{
        ref.child(school).observeEventType(.Value, withBlock: {     (snapshot) in
            let numBuying = snapshot.value!["numBuying"] as! Int // gets numBuying
            if numBuying  > 0 {
                self.noEntries = false
                print("numBuying: ", numBuying) //see console
                indices = numBuying
            }else{
                self.noEntries = true
                indices = 1
            }
        }) { (error) in
            print(error.localizedDescription)
        }
    }



    delay(0.5){
        print("ind: ", indices) // printing correctly
        if(self.noEntries){ // just add one book to get the indices to be 1
            self.books.append(Book(isbn: "", title: "", author: "", edition: "", price: "", uid: ""))

            return
        }
        if self.divider.selectedSegmentIndex == 0{
            self.ref.child(self.school).child("selling").observeEventType(.Value, withBlock: {    (snapshot) in
                let booksJSON = snapshot.value! as! NSArray

                for bookJSON in booksJSON { // add the book to the array
                    let tempAuthor = bookJSON["authors"] as! String
                    let tempTitle = bookJSON["title"] as! String
                    let tempEdition = bookJSON["edition"] as! String
                    let tempPrice = bookJSON["price"] as! String
                    let tempISBN = bookJSON["isbn"] as! String
                    let tempUID = bookJSON["uid"] as! String
                    self.books.append(Book(isbn: tempISBN, title: tempTitle, author: tempAuthor, edition: tempEdition, price: tempPrice, uid: tempUID))
                }

            }) { (error) in
                print(error.localizedDescription)
            }
        }else if self.divider.selectedSegmentIndex == 1{
            self.ref.child(self.school).child("buying").observeEventType(.Value, withBlock: {    (snapshot) in
                let booksJSON = snapshot.value! as! NSArray

                for bookJSON in booksJSON { // add the book to the array
                    let tempAuthor = bookJSON["authors"] as! String
                    let tempTitle = bookJSON["title"] as! String
                    let tempEdition = bookJSON["edition"] as! String
                    let tempPrice = bookJSON["price"] as! String
                    let tempISBN = bookJSON["isbn"] as! String
                    let tempUID = bookJSON["uid"] as! String
                    self.books.append(Book(isbn: tempISBN, title: tempTitle, author: tempAuthor, edition: tempEdition, price: tempPrice, uid: tempUID))
                }

            }) { (error) in
                print(error.localizedDescription)
            }
        }
    }

}

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

请记住,我无法在此方法中进行回调,因为它会在加载视图时由程序自动调用。

此外,延迟段正在努力阻止同样的事情发生。问题是我不能将延迟放在返回周围,因为它认为我想为延迟块返回一个 Int。

控制台:

started looking
books.count:  0
started looking
books.count:  0
started looking
books.count:  0
started looking
books.count:  0
numSelling:  6
numSelling:  6
numSelling:  6
numSelling:  6
ind:  6
ind:  6
ind:  6
ind:  6

如您所见,它甚至在从数据库中获取 numSelling 值之前就返回 0。

非常感谢您的帮助,祝您有美好的一天!

【问题讨论】:

  • 可以(并且必须)进行回调。尝试理解异步模式。在重新加载表视图之前不会调用数据源方法。 GCD 中有一些方法可以将任务分组在一起,并在分组任务完成时调用完成块。

标签: ios swift firebase firebase-realtime-database


【解决方案1】:

一旦方法被调用,你不能延迟返回,但你可以让表视图再次调用数据源方法。

最简单的解决方案是在填充数据后(即在 populateArray() 方法结束时)在表格视图上调用 reloadData()。我可能还会将电话转移到其他地方的populateArray()(如果合适的话,可能是viewDidLoad())。

【讨论】:

  • 好的,我会尝试并回复您。感谢您的帮助。
【解决方案2】:

我愿意:

  1. 将“检索正在购买/出售的标题”从 delay 方法中移出。从numSelling/numBuying 的相应observeEventType 中调用它。摆脱delay

  2. 正如 Charles 所说,不要担心当 viewDidLoad 完成时这些值是空的。完成后只需拨打例行电话tableView.reloadData()

  3. 假设您的 UI 显示同时购买和出售两个标题(或者您在它们之间快速跳转并且不想等待检索数据),您的例程可能需要继续检索两个数组,仅在两者都完成后调用reloadData。这意味着您的模型中可能需要两个数组,一个用于booksSelling,一个用于booksBuying

【讨论】:

    猜你喜欢
    • 2015-03-15
    • 2015-02-15
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-05
    • 1970-01-01
    相关资源
    最近更新 更多