web-dev-qa-db-fra.com

Problèmes lors de la tentative de recréation d'une application basée sur SwiftUI à partir d'une session WWDC

J'essaie de recréer le projet SwiftUI démontré lors de la session 204, mais je rencontre des problèmes particuliers.

J'ai écrit cela en regardant la session trouvée ici: https://developer.Apple.com/videos/play/wwdc2019/204

Voici mon code-

ContentView.Swift:

import SwiftUI
struct ContentView : View {
    @ObjectBinding var store = RoomStore()

    var body: some View {
        NavigationView {
            List {
                Section {
                    Button(action: addRoom) {
                        Text("Add Room")
                    }
                }

                Section {

                    ForEach(store.rooms) { room in //Error: Cannot convert value of type '(Room) -> RoomCell' to expected argument type '(_) -> _'
                        RoomCell(room: room)
                    }
                    .onDelete(perform: delete)
                    .onMove(perform: move)
                }
            }
            .navigationBarTitle(Text("Rooms") )
            .NavigationBarItems(trailing: EditButton())
            .listStyle(.grouped)
        }
    }

    func addRoom() {
        store.rooms.append(Room(name: "Hall 2", capacity: 2000))
    }
    func delete(at offsets: IndexSet) {
        store.rooms.remove(atOffsets: offsets) //Error: Incorrect argument label in call (have 'atOffsets:', expected 'at:')
    }
    func move(from source: IndexSet, to destination: Int) {
        store.rooms.move(fromOffsets: source, toOffset: destination) //Error: Value of type '[Room]' has no member 'move'; did you mean 'remove'?
    }
}

#if DEBUG
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        Group {
            ContentView(store: RoomStore(rooms: testData))
            ContentView(store: RoomStore(rooms: testData))
            .environment(\.sizeCategory, .extraExtraExtraLarge)
            ContentView(store: RoomStore(rooms: testData))
            .environment(\.colorScheme, .dark)
            ContentView(store: RoomStore(rooms: testData))
            .environment(\.layoutDirection, .rightToLeft)
            .environment(\.locale, Locale(identifier: "ar"))
        }
    }
}
#endif
struct RoomCell : View {
    let room: Room
    var body: some View {
        return NavigationButton(destination: RoomDetail(room: room) )
        {
            Image(room.thumbnailName)
            .cornerRadius(8)
            VStack(alignment: .leading) {
                Text (room.name)
                Text ("\(room.capacity) peopje")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }
        }
    }
}

Chambre.Swift:

import SwiftUI

struct Room {
    var id = UUID()
    var name: String
    var capacity: Int
    var hasVideo: Bool = false
    var imageName: String { return name }
    var thumbnailName: String { return name + "Thumb" }

}

#if DEBUG

let testData = [
    Room(name: "Observation Deck", capacity: 6, hasVideo: true),
    Room(name: "Executive Suite", capacity: 8, hasVideo: false),
    Room(name: "Charter Jet", capacity: 16, hasVideo: true),
    Room(name: "Dungeon", capacity: 10, hasVideo: true),
    Room(name: "Panorama", capacity: 12, hasVideo: false),
    Room(name: "Oceanfront", capacity: 8, hasVideo: false),
    Room(name: "Rainbow Room", capacity: 10, hasVideo: true),
    Room(name: "Pastoral", capacity: 7, hasVideo: false),
    Room(name: "Elephant Room", capacity: 1, hasVideo: false),

]

#endif

RoomDetail.Swift:

import SwiftUI
struct RoomDetail : View {
    let room: Room
    @State private var zoomed = false
    var body: some View { //Error: Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type
        ZStack(alignment: .topLeading) {
            Image(room.imageName )
                .resizable()
                .aspectRatio(contentMode: zoomed ? .fill : .fit)
                .navigationBarTitle(Text(room.name), displayMode:
                    .inline)
                .tapAction { withAnimation(.basic(duration: 2)) {
                    self.zoomed.toggle() } }
            }
            .frame(minWidth: 0, maxWidth: .infinity, minHeight:
                0, maxHeight: .infinity)
            if room.hasVideo && !zoomed {
                Image(systemName: "video. fill")
                    .font(.title)
                    .padding(.all)
                    .transition(.move(Edge: .leading) )
            }
        }
}

#if DEBUG
struct RoomDetail_Previews : PreviewProvider {
    static var previews: some View {
        Group {
            NavigationView { RoomDetail(room: testData[0]) }
            NavigationView { RoomDetail(room: testData[1]) }
        }
}
}
#endif

RoomStore.Swift:

import SwiftUI
import Combine

class RoomStore : BindableObject {
    var rooms: [Room] {
        didSet { didChange.send(Void()) } //Solved
    }
    init(rooms: [Room] = []) {
        self.rooms = rooms
    }
    var didChange = PassthroughSubject<Void, Never>()
}

Messages d'erreur inclus dans le contexte, sous forme de commentaires, dans le code ci-dessus.

8
Isaac

Pour cette erreur: // Erreur: impossible de convertir la valeur de type '(Room) -> RoomCell' en type d'argument attendu '(_) -> _' Implémentez un protocole identifiable dans votre modèle de liste comme celui-ci,

struct Room: Identifiable

Pour celui-ci: // Erreur: étiquette d'argument incorrecte dans l'appel (avoir 'atOffsets:', attendu 'at:') Je pense que ce n'est pas votre problème :) Mais vous pouvez utiliser quelque chose comme ça,

guard let index = Array(offset).first else { return }
store.rooms.remove(at: index)

Et pour celui-ci: // Erreur: la valeur de type '[Room]' n'a pas de membre 'move'; vouliez-vous dire "supprimer"? Comme précédemment, vous pouvez utiliser ce morceau de code pour déplacer

guard let sourceIndex = Array(source).first else { return }
store.rooms.insert(roomStore.rooms.remove(at: sourceIndex), at: destination)

Vous pouvez vérifier le code source terminé, https://github.com/ilyadaberdil/iOS-Samples/tree/master/SwiftUI-Sample

9
Ilyada

Avez-vous essayé de passer Void ()?

class RoomStore : BindableObject {
    var rooms: [Room] {
        didSet { didChange.send(Void()) } 
    }
    init(rooms: [Room] = []) {
        self.rooms = rooms
    }
    var didChange = PassthroughSubject<Void, Never>()
}
3
SMP

Dans Xcode 11 beta 4

L'exigence du protocole BindableObject est désormais willChange au lieu de didChange, et doit maintenant être envoyée avant que l'objet ne change plutôt qu'après qu'il change. Cette modification permet une coalescence améliorée des notifications de modification.

class RoomStore: BindableObject {

    var rooms: [Room] {
        didSet { willChange.send() }
    }

    init(rooms: [Room] = []) {
        self.rooms = rooms
    }

    var willChange = PassthroughSubject<Void, Never>()
}

Pour supprimer et déplacer, utilisez le code ci-dessous.

func delete(at offsets: IndexSet) {
    store.rooms.remove(atOffsets: offsets)
}

func move(from source: IndexSet, to destination: Int) {
    store.rooms.move(fromOffsets: source, toOffset: destination)
}
2
Vinoth Vino

Rooms doit être @Published

class RoomStore: ObservableObject {
    @Published var rooms: [Room] {
        didSet {
            willChange.send()
        }
    }

    init(rooms: [Room] = []) {
        self.rooms = rooms
    }

   var willChange = PassthroughSubject<Void, Never>()
}
1
Rexhin Hoxha

Pour utiliser Room dans votre List, vous devez implémenter le protocole Identifiable. Je l'ai oublié aussi et le message d'erreur SwiftUI:

Impossible de convertir la valeur de type '(Room) -> RoomCell' en type d'argument attendu '(_) -> _'

n'est pas utile.

import SwiftUI

struct Room: Identifiable {
    let id = UUID() 
    ...
}
0
mydefs

Pour supprimer et déplacer, vous pouvez utiliser quelque chose comme ceci:

func delete(at offsets: IndexSet) {
    offsets.sorted { $0 > $1 }.forEach { store.rooms.remove(at: $0) }
}

func move(from source: IndexSet, to destination: Int) {
    source.sorted { $0 > $1 }.forEach { store.rooms.insert(store.rooms.remove(at: $0), at: destination) }
}
0
frin