Parameter Übergabe für CKRecord

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

  • Parameter Übergabe für CKRecord

    Hi zusammen,

    ich bin leider immer noch kein "geübter" SwiftUI Programmierer, aber ich lasse mir den Mut nicht nehmen !!!!!!

    Ich habe eine App zur Verwaltung von Trainingsgeschrieben. Nun wollte ich das Datenmodell um den CKRecord erweitern, bekomme jedoch Folgefehler. Diese kann ich leider nicht lösen, weil ich nicht weiß, wie ich einen CKRecord mit einem Wert befülle, wenn ich den Aufruf einer View mache und den CKRecord übergeben muss.

    Viele Worte, vielleicht aber die falsche Terminologie .... Also, hier ein wenig Code:

    Hier mein Datenmodell:

    Quellcode

    1. struct PracticePictureModel: Hashable {
    2. var pictureId: String
    3. var practiceId: String
    4. var record: CKRecord
    5. var uuid: String = UUID().uuidString
    6. init(pictureId: String, practiceId: String, record: CKRecord, uuid: String) {
    7. self.pictureId = pictureId
    8. self.practiceId = practiceId
    9. self.record = record
    10. self.uuid = uuid
    11. }
    12. }
    13. struct PracticeVideoModel: Hashable {
    14. var practiceId: String
    15. var record: CKRecord
    16. var uuid: String = UUID().uuidString
    17. var videoId: String
    18. init(practiceId: String, record: CKRecord, uuid: String, videoId: String) {
    19. self.practiceId = practiceId
    20. self.record = record
    21. self.uuid = uuid
    22. self.videoId = videoId
    23. }
    24. }
    Alles anzeigen


    Beim Aufruf einer View (StartView) brauche ich die Übergabe von diesen beiden Modellen. Alle Felder sind vom Typ "String", halt nur das Feld "Record" nicht:

    Quellcode

    1. WindowGroup {
    2. StartView(selectedPicture: PictureModel(description: "", link: "", name: "", record: CKRecord, uuid: ""), selectedVideo: VideoModel(description: "", link: "", name: "", record: CKRecord, uuid: ""))
    3. .environmentObject(globalSettings)
    4. .environment(\.colorScheme, .light) // or .dark
    Der Fehler liegt in der Zeile 2. Ich weiß nicht, was ich bei "record:" eingeben soll/muss/kann. Mein Eintrag "CKRecord" funktioniert nicht.

    Mir fehlt gerade so wein wenig der Ansatz, in welche Richtung ich denken muss.

    Vielleicht kann jemand meine Knoten im Kopf lösen und mir helfender Hilfestellung geben ......

    Vielen Dank vorab!

    P.S.: Ich hatte zuvor die App ohne Record am Laufen. Einwandfrei. jedoch hatte ich bis dahin auch keine Löschfunktion von Records. Mit der Delete Funktion habe ich dann das Feld "Record" mit eingefügt und komme nun ins Trudeln :saint:
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Moin,

    ich glaube hier fehlt noch etwas Context - weshalb willst du denn einen CKRecord erstellen, du musst damit ja irgendwas beabsichtigen? Soll das ein neuer sein, soll das ein existierender sein, der gefetched wird? Einfach nur CKRecord zu schreiben ist kein valider Syntax - es wird ein Objekt erwartet, also musst du die Klasse in irgendeiner Form initialisieren, sprich immer in Form von CKRecord(...). Du kannst hier in der Doku ja mal schauen, ob ein geeigneter Initializer für deinen Zweck dabei ist.

    VG
  • fHi Osxer,

    vielen Dank für Deine Antwort. Und ein "Moin" klingt mir sehr vertraut !!!! Ich komme aus dem Landkreis Friesland.

    Etwas Context:

    Ich erstelle eine Liste von Items, welche ich mir aus der iCloud hole. Z.B. alle angebotenen Trainings. Aus dieser Liste möchte ich gern Einträge löschen. Und dann auch in der CloudKit DB löschen.

    Die Delete Funktion, welche ich nutze, erfordert ein "record" mit "recordID". Ich selbst habe die ganze Zeit ohne recordID's gearbeitet (allerdings auch ohne Löschfunktion) und würde es auch weiterhin tun. Gern würde ich meine UUID nutzen, um Items einer Liste (und DB) zu löschen. Aber das habe ich nicht hinbekommen :S

    Die 'deleteItem' Funktion sieht wie folgt aus:

    Quellcode

    1. func deleteItem(indexSet: IndexSet) {
    2. guard let index = indexSet.first else { return }
    3. let item = tournaments[index]
    4. let record = item.record
    5. publicDatabase.delete(withRecordID: record.recordID) { [weak self] (returnedRecordID, returnedError) in
    6. DispatchQueue.main.async {
    7. self?.tournaments.remove(at: index)
    8. self?.fetchItems(recordTypeString: "Tournaments")
    9. } // end dispatchqueue
    10. } // end delete
    11. } // end funtion deleteitem
    Alles anzeigen



    Ich habe jetzt mal die Initialisierung des CKRecord durchgeführt:


    Quellcode

    1. WindowGroup {
    2. StartView(selectedVideo: VideoModel(description: "", link: "", name: "", record: CKRecord(recordType: "Tournaments"), uuid: ""))
    3. .environmentObject(globalSettings)
    4. .environment(\.colorScheme, .light) // or .dark
    5. } // end windowsgroup
    ... und es läuft !!!!!

    Manchmal braucht man nur einen kleinen "Schlag in den Nacken" .... Man fängt neu an zu denken und manchmal hilft es :thumbup:


    Osxer: vielen lieben Dank für den Denkanstoß :thumbsup:

    Ich mach dann erst einmal weiter und werde mit Sicherheit auf weitere Herausforderungen stossen :!: :?:
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • Auch wenn es jetzt funktioniert verstehe ich nicht, warum du dir in der Initialisierung einen Dummy-CKRecord generierst? Wenn du den – wie du schreibst – nur zum Löschen brauchst, ist das unnötig. Du holst dir ja den echten CKRecord aus deiner Liste und legst dafür auch eine Konstante an.

    Und wenn du den CKRecord doch in der Struct brauchst und an anderer Stelle noch mit Daten füllst, dann würde ich alles Optional machen und keine unnötigen Dummy-Daten übergeben.
    So Long, and Thanks for All the Fish.
  • Ich habe mein Datenmodell wie oben beschrieben definiert. In einer weiteren View (StartView.swift) greife ich auf dieses Datenmodell zu (Zeile 20), um es einer weiteren View (PracticeVideoView.swift) zu übergeben (Zeile 37).
    In Zeile 19 und 34 habe ich Punkte eingefügt, weil hier vieles kommt, was nicht zum Thema beiträgt ;)

    StartView.swift:

    Brainfuck-Quellcode

    1. struct StartView: View {
    2. @EnvironmentObject var globalSettings: GlobalSettings
    3. @StateObject private var vmCKDb = CloudKitDBViewModel()
    4. @State var title: String = "Tennis Übungen"
    5. @State var showComposeMessageView: Bool = false
    6. @State var selectedDiscipline = "alle"
    7. @State var selectedCategory = "alle"
    8. @State var isSelected: Bool = false
    9. @State var countPractices: Int = 0
    10. // @State var checked: Bool
    11. @State var isAdminVersion: Bool = UserDefaults.standard.bool(forKey: "isAdminVersion")
    12. @State var showVersionUpdateView: Bool = true
    13. var counter: Int = 0
    14. // var selectedPicture: PictureModel
    15. var selectedVideo: VideoModel
    16. .............
    17. List {
    18. ForEach (vmCKDb.months, id: \.self) { month in
    19. if (!(globalSettings.hidePreviousMonths) || (globalSettings.hidePreviousMonths) && ("\(month.uuid)" >= hideMonthsUntilNumberString)) {
    20. Section {
    21. ForEach (vmCKDb.trainings.filter{ ($0.monthId == ("\(month.uuid)")) }, id: \.self) { training in
    22. ForEach (vmCKDb.practices.filter{ ($0.uuid == ("\(training.practiceId)")) && ( ($0.age == ("\(globalSettings.selectedDiscipline)")) || (globalSettings.selectedDiscipline == ("alle")) ) }, id: \.self) { practice in
    23. NavigationLink(destination:
    24. PracticeVideoPictureView(practice: practice, video: selectedVideo)
    25. ) {
    26. SinglePracticeView(isChecked: false, training: training, practice: practice)
    27. }
    28. } // end foreach practice
    29. } // end foreach practices
    30. } // end section
    31. ............
    Alles anzeigen



    Die PracticeVideoView sieht bei mir so aus. In der Zeile 7 definiere ich die Variable und in Zeile 15 nutze ich sie erstmalig:

    Brainfuck-Quellcode

    1. struct PracticeVideoPictureView: View {
    2. @EnvironmentObject var globalSettings: GlobalSettings
    3. @StateObject private var vmCKDb = CloudKitDBViewModel()
    4. var practice: PracticeModel
    5. var video: VideoModel
    6. @State var title: String = "Videos-Bilder"
    7. var body: some View {
    8. VStack {
    9. GlobalHeaderView(title: $title)
    10. Text("\(vmCKDb.practiceVideo.filter({$0.practiceId == "\(practice.uuid)"}).count) Video(s) - \(vmCKDb.practicePicture.filter({$0.practiceId == "\(practice.uuid)"}).count) Bild(er)")
    11. .bold()
    12. .font(.subheadline)
    13. .padding(.vertical, 0)
    14. .underline()
    15. List {
    16. ForEach(vmCKDb.practiceVideo.filter({$0.practiceId == "\(practice.uuid)"}), id: \.self) { item in
    17. ForEach(vmCKDb.videos.filter({$0.uuid == "\(item.videoId)"}), id: \.self) { video in
    18. VStack (alignment: .leading){
    19. Text("\(video.name)")
    20. .bold()
    21. HStack {
    22. YouTubeView(videoId: video.link)
    23. .scaledToFit()
    24. .padding()
    25. } // end hstack
    26. .padding()
    27. Text("\(video.description)")
    28. .font(.footnote)
    29. } // end vstack
    30. .padding()
    31. } // end foreach
    32. } // end foreach
    33. ..............
    Alles anzeigen

    Die StartView wird aus meiner TennisPracticeApp.swift Datei heraus aufgerufen:

    Quellcode

    1. import SwiftUI
    2. import CloudKit
    3. @main
    4. struct TennisPractiseApp: App {
    5. @StateObject var globalSettings: GlobalSettings = GlobalSettings()
    6. var body: some Scene {
    7. WindowGroup {
    8. StartView(selectedVideo: VideoModel(description: "", link: "", name: "", record: CKRecord(recordType: "Tournaments"), uuid: ""))
    9. .environmentObject(globalSettings)
    10. .environment(\.colorScheme, .light) // or .dark
    11. } // end windowsgroup
    12. } // end some scene
    13. } // end struct
    Alles anzeigen
    Wenn ich die Übergabe der Informationen zu "selectVideo" in Zeile 10 weglasse, dann kommt folgender Fehler: Missing argument for parameter 'selectedVideo' in call

    Hoffentlich habe ich nun niemanden verwirrt !
    Ob das jetzt alles "das beste Weg" ist, den ich da nutze, weiß ich (leider) nicht ?( Aber es läuft erst einmal <X <X <X

    Sollte man es anders machen, dann immer her mit einem Tipp/Hinweis .....
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil:
  • freelancer schrieb:

    Wenn ich die Übergabe der Informationen zu "selectVideo" in Zeile 10 weglasse, dann kommt folgender Fehler: Missing argument for parameter 'selectedVideo' in call
    Deshalb sage ich ja, die zu ermittelnden Daten lieber als Optional anlegen:

    Quellcode

    1. struct PracticePictureModel: Hashable {
    2. var pictureId: String?
    3. var practiceId: String?
    4. var record: CKRecord?
    Wobei es – jetzt wo man mehr Code sieht – vermutlich der bessere Weg ist, das Model selbst so zu lassen und die Model-Instanz Optional zu definieren:


    Quellcode

    1. struct StartView: View {
    2. var selectedPicture: PictureModel?
    3. var selectedVideo: VideoModel?

    Variante 2 wäre es meiner Meinung nach deutlich sauberer und du kannst auch einfacher Platzhalter anzeigen, so lange die Daten noch nicht geladen wurden.
    So Long, and Thanks for All the Fish.
  • Danke für den Hinweis.
    Manchmal könnte es so einfach sein !!!! Man vergißt die einfachsten Dinge .... Aber, Übung macht den Meister !


    Allerdings bekomme ich, sobald ich die Variante 2 wähle, einen Compilerfehler: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
    :evil: ;( :( ... aller Anfang ist schwer ... ?( <X :evil: