iosswiftswiftuicloudkitcollaboration

How to use SWCollaborationView in SwiftUI?


SWCollaborationView was introduced as a standard UI element to manage real-time collaboration between users in iOS16+. This is explained in this Apple article. Similarly to UICloudSharingController, it's way to view participants to a share and manage sharing.

Given that UICloudSharingController is broken in iOS16+ (see this), how can I use SWCollaborationView in SwiftUI?

My failed attempts so far:

The the WWDC22 talk introducing SWCollaborationView, the speaker embedded SWCollaborationView in UIBarButtonItem(customView:). I was not able to embed UIBarButtonItem(customView:) into my SwiftUI lifecycle app, because UIBarButtonItem does not conform to UIView and therefore cannot be introduced using UIViewRepresentable.

I also tried wrapping SWCollaborationView in UIViewRepresentable and introducing it directly. The result was identical to this post. When I wrapped it in ToolbarItem, the icon appeared but no action happened on tap. When I wrapped it in ToolbarItem and Button that would open an identical collaboration view as a popover, the icon appeared (screenshot1) and on tap opened a popover where the same icon would appear (screenshot2. Only a second tap would correctly open the desired popover inherent to SWCollaborationView (screenshot3). The code for this is below.


import SwiftUI
import CloudKit
import SharedWithYou

struct DetailView: View {
  var photo: Photo // some object saved in CloudKit, in this example a photo
  @State var showPopover = false
  @Binding var activeCover: ActiveCover? // for dismissal (not relevant for SWCollaborationView)

  var body: some View {
    NavigationView {
      VStack {
        Text("Some content of detail view")
      }
      .toolbar {
        if let existingShare = PersistenceController.shared.existingShare(photo: photo) {  // get the existing CKShare for this object (in this case we use NSPersistentCloudKitContainer.fetchShares, but that's not really relevant)
          ToolbarItem(placement: .automatic) {
            Button(action: {
              showPopover.toggle()
            }){
              CollaborationView(existingShare: existingShare) // <- icon appears, but without the number of participants
            }
            .popover(isPresented: $showPopover) {
              CollaborationView(existingShare: existingShare) // <- icon appears AGAIN, with the number of participants. Instead, we want a popover inherent to SWCollabroationView!
            }
          }
        }
        ToolbarItem(placement: .automatic) {
          Button("Dismiss") { activeCover = nil }
        }
      }
    }
  }
}

struct CollaborationView: UIViewRepresentable {
  let existingShare: CKShare

  func makeUIView(context: Context) -> SWCollaborationView {
    let itemProvider = NSItemProvider()
    itemProvider.registerCKShare(existingShare,
                                 container: PersistenceController.shared.cloudKitContainer,
                                 allowedSharingOptions: .standard)
    let collaborationView = SWCollaborationView(itemProvider: itemProvider)
    collaborationView.activeParticipantCount = existingShare.participants.count
    return collaborationView
  }
  func updateUIView(_ uiView: SWCollaborationView, context: Context) {
  }
}

Solution

  • I submitted a TSI about this; Apple confirmed that SWCollaborationView is not compatible with SwiftUI at the moment and we should submit feedback.