2015-11-14 3 views
2

Я пытаюсь создать массив PFObjects, называемый «areaList». Я немного разбираюсь в этом и понимаю, что я мог бы воспользоваться обработчиком завершения для обработки асинхронного характера загруженных результатов. Мой вопрос, в частности, заключается в том, чтобы получить некоторые рекомендации о том, что я делаю неправильно, а также о потенциальных советах о том, как добиться результата «лучше».Обработчик завершения - Parse + Swift

Вот моя функция запроса с обработчиком завершения:

func loadAreasNew(completion: (result: Bool) ->()) -> [Area] { 
     var areaList = self.areaList 
     let areaQuery = PFQuery(className: "Area") 
     areaQuery.findObjectsInBackgroundWithBlock { 
      (areas: [PFObject]?, error: NSError?) -> Void in 
      if error == nil { 
       for area in areas! { 
        let areaToAdd = area as! Area 
        areaList.append(areaToAdd) 
//     print(areaList) // this prints the list each time 
//     print(areaToAdd) // this prints the converted Area in the iteration 
//     print(area) // this prints the PFObject in the iteration 
        if areaList.count == areas!.count { 
         completion(result: true) 
        } else { 
         completion(result: false) 
        } 
       } 
      } else { 
       print("There was an error") 
      } 
     } 
     return areaList 
    } 

Вот как я пытаюсь вызвать его в viewDidLoad:

loadAreasNew { (result) ->() in 
    if (result == true) { 
     print(self.areaList) 
    } else { 
     print("Didn't Work") 
    } 
} 

я присвоил эту переменную перед viewDidLoad:

var areaList = [Area]() 

В консоли я получаю следующее:

Didn't Work 
Didn't Work 
Didn't Work 
Didn't Work 
[] 

Представляя 5 пунктов, которые я знаю, есть в Parse ...

ответ

2

Это интересный вопрос. Во-первых, PFQuery в основном имеет встроенный обработчик завершения, что очень приятно! Как вы, наверное, знаете, весь код в areaQuery.findObjectsInBackgroundWithBlock {...} запускает ПОСЛЕ ответа сервера. Заполнение чаще всего служит для создания блока, с возможностью асинхронного возвращения данных и ошибок.

Лучшая практика (IMO), чтобы просто вызвать код, который вы хотите использовать, с результатами вашего PFQuery сразу после вашего цикла добавления области (который я собираюсь вынуть, потому что я придирчив к этому), например так:

 func loadAreasNew() { 
     var areaList = self.areaList 
     let areaQuery = PFQuery(className: "Area") 
     areaQuery.findObjectsInBackgroundWithBlock { 
      (areas: [PFObject]?, error: NSError?) -> Void in 
      if error == nil { 
       let areasFormatted = areas! As [Areas] 
       areasList += areasFormatted 
       //Something like this 
       self.codeINeedAreasFor(areasList) 
       } 
      } else { 
       print(error) 
      } 
     } 
    } 

ОДНАКО! Если вы, действительно, считают, что использовать некоторые завершающие обработчики, заканчивая this other answer для получения дополнительных сведений о способах их использования. Но имейте в виду, что у всех инструментов есть время и место ...

+0

Я чувствовал, как это было несколько ног, но после некоторой корректировки синтаксиса, я действительно не работает для меня почему-то. Я заменил часть «codeINeed» простой «печатью», чтобы проверить ее, и это даже не сработало. Опять же, я приеду утром утром. Спасибо за ответ! –

+0

В конечном счете, я выбрал этот ответ, выполнив несколько вещей. Во-первых, я закончил использование ParseUI, у которого есть свой собственный подкласс для обработки возвращаемых массивов PFObjects и представления этого в виде таблицы. Что касается вашей логики, вы были мертвы - у PFQuery есть свой собственный обработчик завершения, также я закончил работу с «CodeINeed» в функции, как вы предложили. Благодаря! –

1

Здесь есть несколько проблем.

Ваш обработчик завершения не требует, чтобы определить имя для параметров ваших завершающих обработчика, так что вы можете легко использовать completion: (Bool) ->()

Далее в функции, вы возвращение areaList. Это нужно поместить через обработчик завершения, как этот onComplete(areaList), и изменить параметр обработчика завершения, чтобы ожидать, что ваш список областей.

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

loadAreasNew { result in 
    if (result == true) { 
     print(self.areaList) 
    } else { 
     print("Didn't Work") 
    } 
} 
+0

Мне нравится это мышление, я обращусь к нему утром. Я понимаю ваш первый комментарий о том, что вам не нужны именованные параметры, поэтому вы можете это исправить. Я не смог исправить вашу вторую часть о том, чтобы поместить areaList в обработчик завершения. Я приеду к нему свежим утром, если у вас нет образца для этого. MY END GOAL состоит в том, чтобы получить список PFObjects (Areas) из функции, чтобы я мог использовать их в качестве указателей и/или заполнять tableViews и т. Д. –

+0

Конечно, вы должны включить areaList в качестве параметра completeHandler. Тогда ваш результат, который вы используете в 'result in ...', будет вашим областным списком. В качестве примера предположим, что areaList является [String]. 'func example (completeHandler: ([String]) ->()) {}' Посмотрите на ответ MacLean ниже. –

1

Вот моя забота:

1) Не передавайте в локальной переменной и сделать возврат функции это, это бессмысленно и опасно.

Возможно, вы захотите инициировать пустой массив и сделать свою выборку, а затем «вернуть» ее.

2) Запрос на выборку обрабатывается в фоновом режиме, вы не будете знать, когда он будет завершен. Если вы немедленно вернете массив, он всегда будет пустым массивом.

Положите «возврат» в ваше завершение.

3) Parse уже имеет метод проверки расстояния, вам не нужно делать это вручную. aPARSEQUERRY.where (ключ:, nearGeoPoint:, inKilometers :)

Я переписать функцию:

func loadNewAreas(completion:([Area],err?)->()){ 
    let areaQuery = PFQuery(className: "Area") 
    areaQuery.where("location",nearGeoPoint:MYCURRENTLOCATION,inKilometers:50) 
    areaQuery.findObjectInBackgroundWithBlock(){objects,err 
     if objects.count == 0 
     { 
      completion([],err) 
     } 
     let areas = Area.areasFromPFObjects(objects) 
     completion(areas,err) 
    } 
} 
+0

Благодарим вас за предупреждение о передаче локальных переменных, а затем заставив его вернуть его. Я надеялся объявить это, заполнить его, а затем вернуть его полностью PFObjects. Может быть, я прихожу к этому неправильно. Я попытаюсь переписать часть «возвращения». Что касается GeoPoints, не совсем то, что мне сейчас нужно, но очень ценю, что вы думаете за пределами пресловутой коробки ... –

Смежные вопросы