Как использовать findObjectsInBackgroundWithBlock в queryTable() класса PFQueryTableViewController

У меня есть класс, который расширяет PFQueryTableViewController. В этого класса реализация queryForTable(), я пытаюсь добавить некоторые данные для построения запроса, используя findObjectsInBackgroundWithBlock. Проблема в том, что, поскольку findObjectsInBackgroundWithBlock является асинхронным, как мне использовать данные, которые я получаю от findObjectsInBackgroundWithBlock, и использовать их для построения query ниже и выполнения return query.

Мой код и ошибка показаны ниже.

override func queryForTable() -> PFQuery {
    let query = PFUser.query()
    //let query = PFQuery(className: "Room")

    query?.whereKey("objectId", notEqualTo: PFUser.currentUser()!.objectId!)

    //Showing OnlineUsers only
    let onlineUsersQuery = PFQuery(className: "OnlineUsers")
    onlineUsersQuery.whereKey("user", equalTo: PFUser.currentUser()!)
    onlineUsersQuery.findObjectsInBackgroundWithBlock({ (results:[AnyObject]?, error:NSError?) -> Void in

        let usersOnlineNow = results as! [PFObject]
        for user in usersOnlineNow {

            self.mLog.printToLog("Select only users who are in the OnLineUsers column")
            query?.whereKey("objectId", equalTo: PFUser.currentUser()!.objectId!)
            //query?.whereKey("objectId", equalTo: "noone")

            if self.searchInProgress {
                query!.whereKey("username", containsString: self.searchString)
            }

            if self.objects!.count == 0 {
                //https://groups.google.com/forum/#!topic/parse-developers/7O9YCHNbuEo
                query!.cachePolicy = PFCachePolicy.CacheThenNetwork //kPFCachePolicyCacheThenNetwork
                //query.cachePolicy = kPFCachePolicyCacheThenNetwork
            }

            query!.orderByAscending("username")

            return query!

        }

    })

//        query!.orderByAscending("username")
//        
//        return query!
}

Изображение, показывающее функцию и ошибку


person user1406716    schedule 17.05.2015    source источник
comment
Может быть множество решений. Я бы создал запрос на завершение colsure и вызвал бы запрос прямо там. Если это слишком сложно, установите переменную экземпляра PFQuery и обновите ее при закрытии завершения. Добавьте наблюдатель свойства в свойство запроса и вызовите то, что вам нужно, в didSet{}   -  person kandelvijaya    schedule 17.05.2015


Ответы (3)


Не делай этого там. Если вам нужна эта информация для заполнения таблицы, получите ее, а затем создайте/перезагрузите таблицу, как только она у вас появится, и поэтому вы можете создать соответствующий запрос.

Вы можете изначально удерживать пользователя на другом экране, чтобы вам не приходилось возиться с загрузкой/выгрузкой представления таблицы или попыткой предоставить запрос-заполнитель.

person Wain    schedule 17.05.2015

Я бы создал запрос на завершение colsure и назвал бы запрос «прямо здесь».

Если это слишком сложно, установите переменную экземпляра PFQuery и обновите ее при закрытии завершения. Добавьте наблюдатель свойства в свойство запроса и вызовите то, что вам нужно, в didSet{}

    var query = PFUser.Query()

    var finalquery:PFQuery{
    didSet{
        //call some function here
        //executeQuery(query)
    }
}

Еще одно: определите переменную запроса вне функции, замыканию будет легко захватить переменную.

При установке значения из-за завершения закрытия текущего фонового вызова функции queryForTable().

onlineUsersQuery.findObjectsInBackgroundWithBlock({ (results:[AnyObject]?, error:NSError?) -> Void in

    let usersOnlineNow = results as! [PFObject]
    for user in usersOnlineNow {

        self.mLog.printToLog("Select only users who are in the OnLineUsers column")
        query?.whereKey("objectId", equalTo: PFUser.currentUser()!.objectId!)
        //query?.whereKey("objectId", equalTo: "noone")

        if self.searchInProgress {
            query!.whereKey("username", containsString: self.searchString)
        }

        if self.objects!.count == 0 {
            //https://groups.google.com/forum/#!topic/parse-developers/7O9YCHNbuEo
            query!.cachePolicy = PFCachePolicy.CacheThenNetwork //kPFCachePolicyCacheThenNetwork
            //query.cachePolicy = kPFCachePolicyCacheThenNetwork
        }

        query!.orderByAscending("username")

        self.finalquery = query

    }

})

Дайте мне знать, если я неправильно понял, я постараюсь уточнить. Ваше здоровье.

person kandelvijaya    schedule 17.05.2015

У меня такая же проблема. Когда представление загружается, вызывается queryForTable, и в идеале он должен немедленно вернуть запрос для pftable. Мой запрос потребовал несколько других запросов для ручного построения условий. Поэтому я решил отправить фоновый поток, который будет строить реальный запрос, и немедленно возвращать pfquery, который выбрал правильный класс синтаксического анализа, но не строки.

Это приводит к успешному завершению queryForTable и немедленному отображению интерфейса таблицы без предупреждений о медленных запросах, выполняемых в основном потоке. Затем, когда мой фоновый запрос завершается, я обновляю сохраненную переменную pfquery и вызываю перезагрузку данных таблицы.

Логика такова:

  • при загрузке представления установите для логического флага для queryIsReady значение false и значение pfquery, которое возвращает класс без строк.

  • в queryForTable, если queryIsReady == false, отправить фоновый поток для создания реального pfquery и вернуть pfquery по умолчанию, который не дает строк.

  • когда фоновый поток завершится, установите для переменной pfquery новые необходимые значения и установите queryIsReady = true

  • вызовите перезагрузку данных таблицы, которая повторно вызовет queryForTable

Если какие-либо другие действия приводят к тому, что queryForTable запускается до завершения фонового потока, логическое значение queryIsReady будет ложным, и будет использоваться пустой результирующий набор.

person NoelHunter    schedule 13.04.2017