In meiner iOS-App habe ich zwei Firebase-bezogene Funktionen, die ich innerhalb von viewDidLoad() aufrufen möchte. Der erste wählt ein zufälliges Kind mit .queryOrderedByKey()
aus und gibt den Schlüssel des Kindes als Zeichenfolge aus. Der zweite verwendet diesen Schlüssel und observeEventType
, um untergeordnete Werte abzurufen und in einem dict zu speichern. Wenn ich diese Funktionen mit einer Schaltfläche in meiner Benutzeroberfläche auslösen, funktionieren sie wie erwartet.Die Swift-Funktion funktioniert in der App, aber nicht in der Override-Funktion viewDidLoad()
Allerdings, wenn ich beiden Funktionen innerhalb viewDidLoad() setzen, bekomme ich diesen Fehler:
Terminating app due to uncaught exception 'InvalidPathValidation', reason: '(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''
Die beanstandeten Codezeilen in meinem AppDelegate.swift sind, rot markiert:
class AppDelegate: UIResponder, UIApplicationDelegate, UITextFieldDelegate
Wenn ich die zweite Funktion auskommentieren und die erste innere viewDidLoad verlassen, wird die App geladen, und nachfolgende Aufrufe beider Funktionen (ausgelöst durch die Schaltfläche Aktion) funktionieren wie erwartet.
Ich habe eine Zeile am Ende der ersten Funktion des URL-Zeichenfolge zu drucken, und es hat keine anstößigen Zeichen: https://mydomain.firebaseio.com/myStuff/-KO_iaQNa-bIZpqe5xlg
ich auch eine Linie zwischen den Funktionen in viewDidLoad hinzugefügt Hard- Code die Zeichenfolge, und ich lief in der gleichen InvalidPathException Problem.
Hier mein viewDidLoad() Func ist:
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
pickRandomChild()
getChildValues()
}
Dies ist die erste Funktion:
func pickRandomChild() -> String {
var movieCount = 0
movieRef.queryOrderedByKey().observeEventType(.Value, withBlock: { (snapshot) in
for movie in snapshot.children {
let movies = movie as! FIRDataSnapshot
movieCount = Int(movies.childrenCount)
movieIDArray.append(movies.key)
}
repeat {
randomIndex = Int(arc4random_uniform(UInt32(movieCount)))
} while excludeIndex.contains(randomIndex)
movieToGuess = movieIDArray[randomIndex]
excludeIndex.append(randomIndex)
if excludeIndex.count == movieIDArray.count {
excludeIndex = [Int]()
}
let arrayLength = movieIDArray.count
})
return movieToGuess
}
Hier ist die zweite Funktion:
func getChildValues() -> [String : AnyObject] {
let movieToGuessRef = movieRef.ref.child(movieToGuess)
movieToGuessRef.observeEventType(.Value, withBlock: { (snapshot) in
movieDict = snapshot.value as! [String : AnyObject]
var plot = movieDict["plot"] as! String
self.moviePlot.text = plot
movieValue = movieDict["points"] as! Int
})
return movieDict
)
Und für eine gute Maßnahme, Hier ist der relevante Teil meiner AppDelegate.swift:
import UIKit
import Firebase
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UITextFieldDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
return true
}
Ich rate Swift führt den Code nicht in der Reihenfolge, die ich erwarte. Wird Swift nicht automatisch auf die erste Funktion warten, bevor die zweite ausgeführt wird? Wenn dies der Fall ist, warum funktioniert dieses Pairing an anderer Stelle in der App, aber nicht in viewDidLoad?
Danke. Ich habe meine Frage mit den Funktionen selbst aktualisiert. – adsigel
Ich habe Ihre geänderten Funktionen verwendet, und die einzige Änderung war ein Swift-Vorschlag zum Hinzufügen einer fehlenden Argumentbezeichnung zu "completion (movieToGuess)" und "completion (movieDict)" am Ende von beiden. Allerdings, wenn ich die Funktionen in viewDidLoad() aufrufen, bekomme ich den Fehler ** Kann nicht konvertiert Wert des Typs 'String' in den erwarteten Argumenttyp '(MovieToGuess: String) ->()'. ** Nichts, was ich versucht habe Dieser Fehler wurde behoben, daher wird die App nicht erstellt. – adsigel
Rufen Sie meine Methode an. Und doppelklicken Sie auf alle möglichen Parameter im View-Controller. Sie erhalten eine Sperrung wie in Firebase, in der Ihre Daten enthalten sind. Du wirst also etwas wie self.myDict machen wollen (was eine Variable ist, die du im View-Controller erstellst) = myDict (die sich innerhalb des Closings befindet.) - Kopiere, wie ich es am Anfang meines Posts gemacht habe. – TrickSpades