Я продолжаю получать ошибку SIGABRT при попытке прочитать мою базу данных firebase и создать массив объектов с ее содержимым. Что я делаю неправильно? - PullRequest
0 голосов
/ 18 февраля 2020

Я сделал все вещи из SDK, которые Firebase велел мне делать, например, добавил их plist-файл и делал вещи в моем файле AppDelegate.swift. К сожалению, он разбился каждый раз. Я хочу, чтобы данные моей базы данных были помещены в массив объектов Repo.

Изображение базы данных: https://i.stack.imgur.com/kfS0v.png

Моя ошибка:

2020-02-17 19:11:44.788063-0600 RepoFinder[23102:1025340] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<FIRDataSnapshot 0x600003b8c9a0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff23c7127e __exceptionPreprocess + 350
    1   libobjc.A.dylib                     0x00007fff513fbb20 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff23c70e49 -[NSException raise] + 9
    3   Foundation                          0x00007fff25713f47 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 225
    4   Foundation                          0x00007fff25712bba -[NSObject(NSKeyValueCoding) valueForKey:] + 317
    5   RepoFinder                          0x00000001043f0845 $s10RepoFinder15ContactFirebaseC04makeA5ArraySayAA0A0CGyFySo15FIRDataSnapshotCcfU_ + 261
    6   RepoFinder                          0x00000001043f0e26 $sSo15FIRDataSnapshotCIegg_ABIeyBy_TR + 70
    7   RepoFinder                          0x00000001044395f6 __63-[FIRDatabaseQuery observeEventType:withBlock:withCancelBlock:]_block_invoke + 118
    8   RepoFinder                          0x000000010441a7fc __43-[FChildEventRegistration fireEvent:queue:]_block_invoke.66 + 124
    9   libdispatch.dylib                   0x0000000105333dd4 _dispatch_call_block_and_release + 12
    10  libdispatch.dylib                   0x0000000105334d48 _dispatch_client_callout + 8
    11  libdispatch.dylib                   0x0000000105342de6 _dispatch_main_queue_callback_4CF + 1500
    12  CoreFoundation                      0x00007fff23bd4049 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    13  CoreFoundation                      0x00007fff23bceca9 __CFRunLoopRun + 2329
    14  CoreFoundation                      0x00007fff23bce066 CFRunLoopRunSpecific + 438
    15  GraphicsServices                    0x00007fff384c0bb0 GSEventRunModal + 65
    16  UIKitCore                           0x00007fff48092d4d UIApplicationMain + 1621
    17  RepoFinder                          0x00000001043da0db main + 75
    18  libdyld.dylib                       0x00007fff5227ec25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

Код для моего класса Repo:

import UIKit

class Repo {

    var name: String = ""
    var icon: String = ""
    var url: String = ""

}

И, наконец, мой код для попытки создать массив объектов репо с данными базы данных Firebase:

import UIKit
import Firebase
import FirebaseDatabase

class ContactFirebase {

    var repoArray = [Repo]()

    func makeRepoArray() -> [Repo] {


        let databaseRef = Database.database().reference()
        databaseRef.child("repos").queryOrderedByValue().observe(.childAdded) { (snapshot) in

            let repo = Repo()

            let name = snapshot.value(forKey: "name")
            let url = snapshot.value(forKey: "url")

            repo.name = name as! String
            repo.url = url as! String

            self.repoArray.append(repo)



        }
        return repoArray
    }
}

Спасибо :)

1 Ответ

0 голосов
/ 24 февраля 2020

Firebase является асинхронным, и данные, возвращаемые из Firebase, действительны только в замыкании, следующем за функцией. Кроме того, код работает быстрее, чем inte rnet:

databaseRef.child("repos").queryOrderedByValue().observe(.childAdded) { (snapshot) in
   //Firebase data is valid here but takes time to return from Firebase
}
//any code following the closure will run *before* the code in the closure.

Существует несколько опций

1) Считывание данных по .value, повторение заполнения массива

databaseRef.child("repos").queryOrderedByValue().observeSingleEvent(of: .value, with: { snapshot in

let allChildNodes = snapshot.children.allObjects as! [DataSnapshot]
   for child in allChildNodes {
      //create repoObject
      self.repoArray.append(repoObject)
   }
   //reload your tableView or whatever you want to do with the array
}

2) Использование событий .value всегда запускается после .childAdded событий

var initialRead = true

func readTheRepos() {
    let reposRef = self.ref.child("repos")

    reposRef.observe(.childAdded, with: { snapshot in
        //create repoObject
        self.repoArray.append(repoObject)

        if self.initialRead == false {
            print("a new repo was added") //executes only after the initial read of all repos
        }
    })

    reposRef.observeSingleEvent(of: .value, with: { snapshot in
        print("inital load has completed and the last repo was read")
        self.initialRead = false
    })
}

3) Вести подсчет общего количества репо в узле репо в другой узел и сравните его, так как репозитории читаются через .childAdded

totalRepoCount = //get this from another node
currentCount = 0
reposRef.observe(.childAdded, with: { snapshot in
   //create repoObject
   self.repoArray.append(repoObject)
   currentCount += 1
   if currentCount == totalRepoCount {
      //last repo was read
   }
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...