Что использовать вместо 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)
}
}
}
})
Это должно исправить вашу проблему.