Что использовать вместо indexPath.row? за не стол?

Я работаю с видом карты, а не с таблицей, но я не знаю, что использовать для замены indexPath.row.

У меня есть вид карты с аннотациями, когда нажимается информационная кнопка аннотации, я затем запрашиваю свою базу данных CK и возвращаю запись, у которой есть поле имени, совпадающее с названием нажатой аннотации. Это возвращает [CKRecord] с одной записью, так как нет подходящих имен.

На этом этапе с помощью таблицы я бы сделал следующее для доступа к данным...

let placeInfo = selectedData[indexPath.row]
let placeName = placeInfo.objectForKey("Name") as! String
let placeCity = placeInfo.objectForKey("City") as! String

Однако, так как я не использую tableview, у меня нет indexPath для использования. Поскольку мой объект [CKRecord] содержит только одну запись, я подумал, что мог бы заменить indexPath.row на расположение массива записи...

let placeInfo = selectedPlace[0] //also tried 1

Эта строка создает ошибку индекса вне диапазона.
Я перепробовал все, что знаю, и, как вы можете себе представить, на данный момент я не очень хорош в Swift или в программировании в целом.

Вот полная функция mapView, которую я использую...

    func mapView(mapView: MKMapView, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {

    let cloudContainer = CKContainer.defaultContainer()
    let publicData = cloudContainer.publicCloudDatabase

    let tappedPlace = annotationView.annotation!.title!! as String

    let predi = NSPredicate(format: "Name = %@", tappedPlace)
    let iquery = CKQuery(recordType: "Locations", predicate: predi)

    publicData.performQuery(iquery, inZoneWithID: nil, completionHandler: {
        (results, error) -> Void in

        if error != nil {
            print(error)
            return
        }

        if let results = results {
            print("Downloaded data for selected location for \(tappedPlace)")

            NSOperationQueue.mainQueue().addOperationWithBlock() {
                self.selectedPlace = results
            }
        }
    })

    let placeInfo = selectedPlace[0]
    let placeName = placeInfo.objectForKey("Name") as! String
    //returns Index out of range error for placeInfo line


    //need data before segue
    //performSegueWithIdentifier("fromMap", sender: self)
}

1 ответ

Решение

Ваша проблема в том, что вы пытаетесь получить доступ к selectedPlace до того, как он действительно будет подписан вашим обработчиком завершения. Ваш publicData.performQuery кажется асинхронной операцией, и это означает, что элемент управления выйдет из этого вызова даже до того, как обработчик завершения будет выполнен (это ожидается в случае асинхронного вызова). И вы сразу достигаете линии

let placeInfo = selectedPlace[0]

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

publicData.performQuery(iquery, inZoneWithID: nil, completionHandler: {
    (results, error) -> Void in

    if error != nil {
        print(error)
        return
    }

    if let results = results {
        print("Downloaded data for selected location for \(tappedPlace)")

        NSOperationQueue.mainQueue().addOperationWithBlock() {
            self.selectedPlace = results
               if(results.count > 0){

               let placeInfo = selectedPlace[0]
               let placeName = placeInfo.objectForKey("Name") as! String
               //Do any other computations as needed.
               performSegueWithIdentifier("fromMap", sender: self)
            }
        }
    }
})

Это должно исправить вашу проблему.

Другие вопросы по тегам