insidegui / MultipeerKit

MultipeerConnectivity + Codable = ❤️
BSD 2-Clause "Simplified" License
1.1k stars 71 forks source link

XCode 13.4.1 (13F100) - dataSource.availablePeers error #28

Closed pawisoon closed 2 years ago

pawisoon commented 2 years ago

Hi all,

I attempted to recreate sample code in Xcode 13.4.1. I added swift package of MultipeerKit, copied sample files, added keys to info.plist new location and I'm getting the following error: Thread 1: Fatal error: No ObservableObject of type MultipeerDataSource found. A View.environmentObject(_:) for MultipeerDataSource may be missing as an ancestor of this view. in ContentView.swift on line: ForEach(dataSource.availablePeers) { peer in

Screenshot 2022-07-17 at 18 09 07

Can anyone reproduce the same issue? Maybe we could create new sample code to support the newest version of Xcode. Sample project from repo runs without problems, problem shows when trying to integrate MultipeerKit to new app.

insidegui commented 2 years ago

Maybe you forgot to add the .environmentObject modifier to your content view?

Like this: https://github.com/insidegui/MultipeerKit/blob/cb78d2c32498f87d398b069052bd5555e29f1fe0/example/MultipeerKitExample/MultipeerKitExample/SceneDelegate.swift#L57

pawisoon commented 2 years ago

Hey, thanks for your response! I got exactly the same files as in Example project with this line. Problem appears in newer version of Xcode which has no AppDelegate.swift and uses this root file to create view:

import SwiftUI

@main
struct TestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
insidegui commented 2 years ago

You need to provide the environment object to the content view, regardless of whether the project uses the app delegate infrastructure or the SwiftUI one.

You could probably do something like this in your TestApp struct:

import SwiftUI
import MultipeerKit

@main
struct TestApp: App {
    // The transceiver here could be stored somewhere else, such as in a static property in
    // the MultipeerTransceiver type itself that you declare in an extension.
    @StateObject var dataSource = MultipeerDataSource(transceiver: transceiver)

    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(dataSource) 
        }
    }
}

You can find more information in this article: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views

I'll close this issue since it's not related to the library itself. If you have more general questions about usage, you can post them on Github Discussions.