web-dev-qa-db-ja.com

WWDCセッションからSwiftUIベースのアプリを再作成しようとする際の問題

セッション204で示されているSwiftUIプロジェクトを再作成しようとしていますが、いくつかの特有の問題が発生しています。

ここにあるセッションを見て、これを書きました: https://developer.Apple.com/videos/play/wwdc2019/204

これが私のコードです

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)
            }
        }
    }
}

Room.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>()
}

上記のコードのコメントとして、コンテキストに含まれるエラーメッセージ。

8
Isaac

このエラーの場合://エラー:タイプ '(Room)-> RoomCell'の値を予期される引数タイプ '(_)-> _'に変換できません識別可能なプロトコルをこのようなリストモデル、

struct Room: Identifiable

この場合://エラー:呼び出しの引数ラベルが正しくありません( 'atOffsets:'があり、 'at:'が必要です)私はそれはあなたの問題ではないと思います:)しかし、あなたはできますこのようなものを使用し、

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

この場合://エラー:タイプ '[Room]'の値にはメンバー 'move'がありません。 「削除」という意味ですか?前と同じように、そのコードを使用して移動できます

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

完成したソースコードを確認できます https://github.com/ilyadaberdil/iOS-Samples/tree/master/SwiftUI-Sample

9
Ilyada

Void()を渡してみましたか?

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

Xcode 11 beta 4

BindableObjectプロトコルの要件はwillChangeではなくdidChangeになり、オブジェクトが変更された後ではなく、変更される前に送信されるようになりました。この変更により、変更通知の合体を改善できます。

class RoomStore: BindableObject {

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

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

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

削除および移動するには、以下のコードを使用します。

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@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

RoomListを使用するには、Identifiableプロトコルを実装する必要があります。私もそれを忘れて、SwiftUIエラーメッセージ:

タイプ '(Room)-> RoomCell'の値を予期される引数タイプ '(_)-> _'に変換できません

役に立たない。

import SwiftUI

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

削除と移動には、次のようなものを使用できます。

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