TEAM LICENSES: Save money and learn new skills through a Hacking with Swift+ team license >>

SOLVED: Preview Crashing When Trying To Iterate Relationship

Forums > SwiftUI

I am currently teaching myself Swift and Swiftui, to that end I am creating an app that is semi useful to me. I have created a peice of functionality that works within the simulator as well as on a physical device but seems to cause a crash in the preview.

I have created the following model:

@Model
final class Hosts{
    @Attribute(.unique)
    var ip: String?

    @Attribute(.unique)
    var api_url: URL

    var connected_too: Hosts? = nil

    @Relationship(inverse: \Hosts.connected_too)
    var connected_from: [Hosts] = []

    var host_description: String?
    var hostname: String

    init(api_url: URL, hostname: String, ip: String?, host_description: String?){
        self.api_url = api_url
        self.host_description = host_description
        self.hostname = hostname.lowercased()
        self.ip = ip
    }
}

I have a view that lists each instance of an object of this model type and I pass in the instance to a further view so that I can see the full details.

so the detail view is is like:

struct HostDetailView: View {
    public var host: Hosts
    .....
}

During processing of this view a method is called:

func get_connected_too(host: Hosts) -> [Hosts]{
    var current_host: Hosts = host
    var connected_hosts: [Hosts] = []
    while (current_host.connected_too != nil) {
        connected_hosts.append(current_host.connected_too!)
        current_host = current_host.connected_too!
    }
    return connected_hosts
}

this produces a list of connected too hosts or an empty list (so think device a is connected to switch b which is connected to router c). As I say this works perfectly on a defvice or on the simulator.

The issue is coming in when I try to create a preview. I have created the following:

struct HostDetailView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            HostDetailView(host: test_data())
                .previewDisplayName("Default mode")

            HostDetailView(host: test_data())
                .preferredColorScheme(.dark)
                .previewDisplayName("Dark mode")
        }
    }
}

func test_data() -> Hosts{
    let router: Hosts = Hosts(api_url: URL(string: "http://google.com")!, hostname: "router", ip: "1.2.3.4", host_description: "Main router")
    let host: Hosts = Hosts(api_url: URL(string: "http://yahoo.com")!, hostname: "router", ip: "2.3.4.5", host_description: "Main router")
    host.connected_too = router
    return host
}

Unfortunately this causes the preview to crash, the pertinent part of the crash report is:

5   HostDetailView.1.preview-thunk.dylib           0x14edb51b4 __preview__get_connected_too(host:) + 140 (HostDetailView.swift:73)
6   HostDetailView.1.preview-thunk.dylib           0x14edb57cc closure #1 in HostLinksStruct.__preview__body.getter + 372 (HostDetailView.swift:44)
7   HostDetailView.1.preview-thunk.dylib           0x14edb5968 partial apply for closure #1 in HostLinksStruct.__preview__body.getter + 16

If I remove the while clause in the get_connected_too function the preview will work, but if I either comment out the content of the while or only the while start and end block the preview wil crash.

I suspect the issue might be with how I am constructing or providing the test data. Can anyone identfy what I might be doing wrong.

2      

Turns out I have actually just managed to fix it myself. by creating a preview in this way instead:

#Preview {
    let config_mem = ModelConfiguration(isStoredInMemoryOnly: true)
    let container = try! ModelContainer(for: Hosts.self, configurations: config_mem)
    let router: Hosts = Hosts(api_url: URL(string: "http://google.com")!, hostname: "router", ip: "1.2.3.4", host_description: "Main router")
    let host: Hosts = Hosts(api_url: URL(string: "http://yahoo.com")!, hostname: "router", ip: "2.3.4.5", host_description: "Main router")
    router.connected_from.append(host)
    container.mainContext.insert(host)
    return HostDetailView(host: host)
            .modelContainer(container)
}

2      

Hacking with Swift is sponsored by Superwall.

SPONSORED Superwall lets you build & test paywalls without shipping updates. Run experiments, offer sales, segment users, update locked features and more at the click of button. Best part? It's FREE for up to 250 conversions / mo and the Superwall team builds out 100% custom paywalls – free of charge.

Learn More

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.