0

The setup:

My app has a View ToolBar (all shortened):

struct ToolBar: View {
    @State private var ownerShare: CKShare?
    @State private var show_ownerModifyShare = false
// …  

The toolbar has some buttons that are created by functions. One of them is

func sharingButton(imageName: String, enabled: Bool) -> SharingButton {
    return SharingButton(systemImageName: imageName, enabled: enabled) {
        Task {
            do {
                (_, participantShare, ownerShare) = try await dataSource.getSharingInfo()
                // …
                if ownerShare != nil { show_ownerModifyShare = true }
            } catch (let error) {
                //...
            }
        }
    }
}

This is the body:

    var body: some View {
        HStack {
            // …
            sharingButton(imageName: "square.and.arrow.up", enabled: currentMode == .displayingItems)
                .fullScreenCover(isPresented: $show_ownerModifyShare) {
                    // A CKShare record exists in the iCloud private database. Present a controller that allows to modify it.
                    CloudSharingView(container: CKContainer(identifier: kICloudContainerID), shareRecord: ownerShare!, dataSource: dataSource)
                }
        }
    }
}

The problem:

When the sharingButton is tapped, ownerShare is set in Task {…}, since the iCloud database is shared as an owner.
Accordingly, show_ownerModifyShare = true is executed, and thus the body of struct ToolBar is newly rendered.
However, CloudSharingView(container: CKContainer(identifier: kICloudContainerID), shareRecord: ownerShare!, dataSource: dataSource) crashes, because ownerShare is nil, although it is only set true after ownerShare has been set != nil.

My question:

What could be the reason, and how to correct the code?

EDIT: (due to the comment of jnpdx):

I replaced .fullScreenCover(isPresented: by

.fullScreenCover(item: $ownerShare) { _ in
  CloudSharingView(container: CKContainer(identifier: kICloudContainerID), shareRecord: ownerShare!, dataSource: dataSource)
}  

but the code still crashes with Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value when ownerShare! is used.

Reinhard Männer
  • 14,022
  • 5
  • 54
  • 116

1 Answers1

1

You should use the item form of fullScreenCover, which allows you to send a dynamically-changed parameter to the inner closure:

.fullScreenCover(item: $ownerShare) { share in
  CloudSharingView(container: CKContainer(identifier: kICloudContainerID), shareRecord: share, dataSource: dataSource)
}  

This is a common issue with sheet and the related functions in SwiftUI, which calculate their closures when first rendered and not at presentation time. See related:

jnpdx
  • 45,847
  • 6
  • 64
  • 94