Swift 3 CoreData Logik "optimieren"

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Swift 3 CoreData Logik "optimieren"

    Hallo zusammen,

    ich habe es ENDLICH geschafft, in macOS mit CoreData zu arbeiten.
    Habe nun einen ViewController, welcher einen TableView, zwei Textfelder und einen Button (Save) hat.

    Textfeld 1 = Vorname
    Textfeld 2 = Nachname
    Button (Save) = Eintrag CoreData
    TableView = Anzeige Einträge CoreData

    Anbei mein Code und ein Screenshot der CoreData Einstellungen
    Bildschirmfoto 2017-04-30 um 16.30.50.png


    Code:

    Quellcode

    1. import Cocoa
    2. class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
    3. @IBOutlet weak var txtVorname: NSTextField!
    4. @IBOutlet weak var txtNachname: NSTextField!
    5. var content = [String]()
    6. func RequestData() {
    7. let appdelegate = NSApplication.shared().delegate as! AppDelegate
    8. let context = appdelegate.persistentContainer.viewContext
    9. let request = NSFetchRequest<NSFetchRequestResult>(entityName: "User")
    10. request.returnsObjectsAsFaults = false
    11. do {
    12. let results = try context.fetch(request)
    13. if results.count > 0 {
    14. for result in results {
    15. if let vorname = (result as AnyObject).value(forKey: "vorname") as? String {
    16. content.append(vorname)
    17. }
    18. if let nachname = (result as AnyObject).value(forKey: "nachname") as? String {
    19. content.append(nachname)
    20. }
    21. }
    22. }
    23. } catch {}
    24. }
    25. func numberOfRows(in tableView: NSTableView) -> Int {
    26. return content.count
    27. }
    28. func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
    29. return content[row]
    30. }
    31. @IBAction func SaveUser(_ sender: Any) {
    32. let appdelegate = NSApplication.shared().delegate as! AppDelegate
    33. let context = appdelegate.persistentContainer.viewContext
    34. let newUser = NSEntityDescription.insertNewObject(forEntityName: "User", into: context)
    35. newUser.setValue(txtVorname.stringValue, forKey: "vorname")
    36. newUser.setValue(txtNachname.stringValue, forKey: "nachname")
    37. do {
    38. try context.save()
    39. } catch {}
    40. }
    41. }
    Alles anzeigen


    Allerdings stört mich die Verwendung meiner variable "content".
    Wie man sehen kann, füge ich Vorname und Nachname nacheinander in diese Variable.

    Ausgabe wie folgt:
    ["Max","Mustermann","Max2", "Mustermann2"] usw

    Das dies nicht elegant ist weiß ich, allerdings habe ich keinen Schimmer wie ich das lösen kann.
    Könnte ihr mir aus der Patsche helfen ?
  • Keine Ahnung. Probiere es mal so:

    var content = [NSManagedObject]()

    BTW: Ich würde ja gerne das Code Tag verwenden, allerdings crasht Safari dann bei mir. Safari ist echt ein klasse Browser geworden, der fast nix mehr kann. :( Wenn das UI von Chrome nicht so k*ck* wäre, dann wäre ich schon umgestiegen. :(
  • Hallo

    Mit Core Data kenne ich mich nicht aus. Da kann ich nicht weiterhelfen. Mir sind bei Durchsicht Deines Codes aber ein paar Kleinigkeiten aufgefallen, die Deinen Code wohl etwas verbessern könnten.

    1.)
    Typdeklarationen, wie z.B. Klassennamen, werden groß geschrieben, Variablen und Funktionsnamen klein. Das ist eine gute alte Konvention, an die man sich besser halten sollte.
    D.h. RequestData() => requestData() und SaveUser(_:) => saveUser(_:)

    2.)

    Quellcode

    1. do {
    2. try context.save()
    3. } catch {}

    Wenn Du einen möglichen Fehler eh nicht abfängst und behandelst, kannst Du Dir das do {} catch {} auch sparen. Einfaches try? context.save() reicht dann.
    Das geht genauso auch weiter oben in Deinem Code. Aus let results = try context.fetch(request) wird guard let results = try? context.fetch(request) else { return } ohne do{} catch{}, und eine lästige Einrückung kann man sich auch sparen. Das gilt natürlich nur, falls Du eine Fehlerbehandlung nicht doch später noch einbauen willst.

    3.)
    if results.count > 0 ist vollkommen überflüssig. Ist das Array leer, wird for result in results eh übersprungen.

    4.)
    Die beiden ifs if let vorname = … und if let nachname = … kannst Du auch durch Komma getrennt in einem Statement abhandeln. Also z.B.

    Quellcode

    1. if let vorname = … ,
    2. let nachname = … {
    3. print(vorname, nachname)
    4. }
    Natürlich nur, wenn man sicher sein will, daß beides zusammen Werte hat.

    Ich hoffe, Du kannst etwas mit diesen Kleinigkeiten anfangen, um Dein Swift zu verbessern.
    Das iPhone sagt: "Zum Antworten streichen". Wie? Echt Jetzt? Muß ich erst die Wohnung streichen!?
  • MCDan schrieb:

    Ich würde ja gerne das Code Tag verwenden, allerdings crasht Safari dann bei mir. Safari ist echt ein klasse Browser geworden, der fast nix mehr kann. :( Wenn das UI von Chrome nicht so k*ck* wäre, dann wäre ich schon umgestiegen. :(
    Ich benutze als vorläufigen Workarount auch den WebKit Nighy Build (Download Archiv) bis Apple das gefixt hat.
    Mit dem läuft es wieder anständig. :|
    * Kann Spuren von Erdnüssen enthalten.
  • PetTus schrieb:

    Könnte ihr mir aus der Patsche helfen ?
    Du hast ja eine Klasse User erstellt. Warum benutzt du die nicht? Statt ein Array von Strings kannst du doch direkt ein Array von User nehmen. Dann kannst du das Ergebnis von try? context.fetch(request) direkt der Instanzvariable var content = [User]? zuweisen und hast dann da deine Daten für die Tabelle zur Verfügung.


    norbi schrieb:

    Da Lob ich mir Cocoa und Bindings aus den guten alte Zeiten. Da braucht man für solche Basics gar keinen Code.
    Ich glaube Cocoa Bindings würde PetTus im Moment noch überfordern.
  • norbi schrieb:

    Da Lob ich mir Cocoa und Bindings aus den guten alte Zeiten. Da braucht man für solche Basics gar keinen Code.
    Naja, eigentlich fluppt das Ganze ja auch noch heutzutage wunderbar. Anscheinend ist es moderner, alles explizit auszudrücken. Also Interface-Elemente komplett per selbstgeschriebenen Code zu verwalten. Lieber hundertmal den gleichen Kram programmieren, als einmal auf Typsicherheit verzichten.
    „Meine Komplikation hatte eine Komplikation.“
  • Ich finde den IB an sich sehr gut, aber was mich mittlerweile tatsächlich dazu treibt, auch Views per code zu erzeugen (in obj-c...), ist das für mein Empfinden kaputte tooling in Xcode mit Autolayout. Plötzlich tauchen wieder irgendwelche Warnungen auf von angeblich falschen frames, das eingebaute "fixing" schiebt alle views weg usw. usw. Wenn es immer funktionieren würde, wäre die fehlende Typsicherheit kein Problem, aber eine view mit Autolayout ist mit dem iOS9 API schneller hingeschrieben als gefühlte Ewigkeiten bei Bluthochdruck mit dem IB zu kämpfen.
  • Ich finde, dass sich gerade der Autolayout-Editor in den letzten Versionen stark verbessert hat. Auch wenn er noch einige kleine Macken hat, kann man damit inzwischen Constraints sehr gut austesten. Die Liniefarben zeigen inzwischen auch recht zuverlässig an, ob man einen grundsätzlichen Fehler oder nur eine Fehlplatzierung im Layout hat.

    Markus Müller schrieb:

    Plötzlich tauchen wieder irgendwelche Warnungen auf von angeblich falschen frames, das eingebaute "fixing" schiebt alle views weg usw
    Das sehe ich schon fast als Feature: Wenn nach einem „Update Views“ die Views nicht an der Stelle sind, wo ich sie haben möchte, mache ich ein Undo und korrigiere die Constraints.

    Zugegebenermaßen waren die ersten Versionen grauenhaft, weil man bei komplexeren Layouts nichts mehr vor Constraints gesehen hat. Inzwischen arbeite ich damit aber richtig gerne.
    „Meine Komplikation hatte eine Komplikation.“