2016-04-23 8 views
0

Ich versuche, eine Kontaktseite einzurichten, wo ich Kontakte hinzufügen/bearbeiten kann. Ich bekomme jedoch einen Nullwert, wenn ich versuche, CoreDataStack.context aufzurufen.Verwalteter Kontext von CoreDataStack bleibt nicht durch die Navigationsleiste

Hier entsteht es in den AppDelegate

lazy var coreDataStack = CoreDataStack() 


func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
    // Override point for customization after application launch. 
    UINavigationBar.appearance().barTintColor = navigationMainColor 
    UINavigationBar.appearance().tintColor = navigationMainItemColor 

    let navigationController = window!.rootViewController as! UINavigationController 
    let listViewController = navigationController.topViewController as! ViewController 
    listViewController.coreDataStack = coreDataStack 

    return true 
} 

ich es zu meinen ersten View-Controller übergeben und innerhalb des RootViewController ich eine Taste, die mich zu einem anderen Ansicht-Controller sendet. Im rootViewController ist der CoreDataStack-Kontext immer noch vorhanden, wenn ich print (coreDataStack) aufruft. Ich weiß also, dass es auf den ersten Blick existiert. Die Schaltfläche, die ich drücke, um zur Kontaktseite zu gelangen, ist eine Balkenschaltfläche in einer Symbolleiste.

Mögliches Problem 1 kann sein, dass ich nicht mit der Navigationsleiste hin und her gehe, aber alle Ansichten sind in einen Navigationsstapel eingebettet.

Muss ich forSegue innerhalb des ersten View-Controllers vorbereiten, um den NSManagedObjectContext zu übergeben?

Zwischen den Kontakten und dem neuen Contact View-Controller befindet sich auch ein Navigationscontroller. Aber das Nil scheint zurückgeschickt zu werden, bevor das überhaupt geschieht. In den Kontakten View-Controller die prepareForSegue, dass der Benutzer überprüft, ob versucht, einen Kontakt hinzuzufügen hier gefunden wird

else if segue.identifier == "AddContact" { 
     let navigationController = segue.destinationViewController as! UINavigationController 
     let addViewController = navigationController.topViewController as! NewContactViewController 
     let contactEntity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: coreDataStack.context) 

     let newContact = Contact(entity: contactEntity!, insertIntoManagedObjectContext: coreDataStack.context) 

     addViewController.contact = newContact 
     addViewController.context = newContact.managedObjectContext 
     addViewController.delegate = self 
    } 

Und die Fehler, die ich bekommen habe ist, dass die coreDataStack.context wenn ich versuche, und erstellen Sie einen neuen Kontakt Nil zurückgeben. Ich habe stundenlang damit herumgetobt und ich glaube, ich vermisse etwas wirklich Kleines oder Großes. So oder so möchte ich einfach Core Data lernen und besser werden.

Antwort

0

mit zugegriffen werden Sie innerhalb der ersten View-Controller prepareForSegue, um ich brauche Übergeben Sie den NSManagedObjectContext?

Ja, das ist genau das Problem, das Sie haben. Sie benötigen eine Dependency Injection selbst tun da Apple kann nicht vorhersagen, wo Sie wollen die Dinge :)

Wenn Ihr eingehender (Ziel) View-Controller in einem Navigationscontroller eingewickelt ist, können Sie sicher davon ausgehen, dass hinweisen, dass die topViewController Ihre Ansicht Controller (und Sie können dies testen) und injizieren.

Also einfach den Navigationscontroller holen und dann den Zielcontroller holen? Ist es einfach eine Frage von destinationcontroller.context = self.context in der Prepareforsegue für den ersten View-Controller?

Andersherum:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    guard let destinationNavController = segue.destinationViewController as? UINavigationController else { 
     print("Unexpected view controller: \(seque.destinationViewController.self)") 
    } 
    guard let myViewController = destinationNavController.topViewController as? MyViewController else { 
     print("Unexpected view controller: \(destinationNavController.topViewController.self)") 
    } 
    myViewController.context = context 
} 

ersetzen Stücke mit Ihrem Namen Klasse je nach Bedarf.

Ja, dachte ich, jetzt bekomme ich einen seltsamen Fehler, dass ich nicht zwingen kann, meinen ContactViewController auf UINavigationController downcast. Ist es möglich, dass sich mein ContactViewController nicht auf dem Navigations-Stack befindet?

OK, Schritt zurück. Wenn Sie nur View-Controller in einem nav Stapel pop'ing werden dann werden Sie Ihre ContactViewController direkt als Ziel bekommen und Sie können die nav-Controller wie folgt überspringen:

func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    guard let myViewController = segue.destinationViewController as? MyViewController else { 
     print("Unexpected view controller: \(destinationNavController.topViewController.self)") 
    } 
    myViewController.context = context 
} 

Wenn die Segue zeigt auf eine NEWUINavigationController dann ist da noch etwas falsch.

+0

Also einfach den Navigationscontroller holen und dann den Zielcontroller holen? Ist es einfach eine Frage von destinationcontroller.context = self.context in der Prepareforsegue für den ersten View-Controller? – ggworean

+0

Antwort aktualisiert, um zu demonstrieren, was ich meine. –

+0

Oh, so ist diese prepareforsegue in der zweiten Ansicht Controller, wo es eine Art von Prepareforsegue empfangenden Art ist. Super, danke – ggworean

0

Ihr Coredatastack sollte ein Singleton-Klassenobjekt sein. Jetzt ein Tag, wenn Sie eine neue Coredata-Anwendung erstellen Apple selbst erstellt den Klempner-Code für Sie in AppDelegate. Da AppDelegate eine Singleton-Klasse ist, können Sie überall in Ihrer Anwendung auf den Coredatastack als AppDelegate.coredatastack zugreifen. Da Sie definiert auch die coredatastack in AppDelegate Sie es in Ihrem Viewcontrollers nicht passieren müssen, kann es direkt

let delegate = UIApplication.sharedApplication().delegate as AppDelegate 
delegate.coredatastack 
+1

Singletons sollten wirklich ** NICHT ** in dieser oder einer anderen Situation verwendet werden. Apples Vorlage ist ein sehr schlechtes Beispiel und schlägt nicht vor Singleton zu erstellen. Außerdem wird Ihre Antwort dem OP nicht helfen, das eigentliche Problem zu lösen. –

+0

Die Fragen besagt, dass Coredatastack Kontext nicht persistent ist. Coredata-Kontext sollte Singleton-Objekt sein. Apple und alle anderen Tutorials basieren nur darauf. Apple selbst erstellt es jetzt standardmäßig als Singleton in AppDelegate. –

+0

Falsch. Apples Template demonstrierte die Erstellung des Core Data Stacks im AppDelegate. Erstens ist das AppDelegate ** NOT ** ein Singleton. Nur weil es eine Instanz eines Objekts gibt, heißt das nicht, dass es ein Singleton ist. Zweitens ist das Template von Apple ein * armes * Beispiel für die Implementierung dieses Stacks und ist alter Code. Sie können dies überprüfen, indem Sie das [Core Data Programming Guide] (https://developer.apple.com/library/watchos/documentation/Cocoa/Conceptual/CoreData/index.html) lesen, das im März dieses Jahres aktualisiert wurde. –

Verwandte Themen