【问题标题】:SwiftUI: How to dismiss a View after Firebase Firestore document changes?SwiftUI:Firebase Firestore 文档更改后如何关闭视图?
【发布时间】:2021-06-11 02:16:30
【问题描述】:

TLDR:当NavigationLinkuserId 不再在数组中时,我如何关闭当前视图。

我正在尝试为所有者创建一个“踢出”功能来踢出其他用户。不过,在为 Space 文档的任何更改设置监听器后,我不确定如何为 ID 不在 Space 数组中的用户调用 presentationMode.wrappedValue.dismiss()

空间视图

    struct SpaceView: View {
        
        @ObservedObject var spaceViewModel: SpaceViewModel
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
        var body: some View {
            ZStack {
                VStack(spacing: 15) {
                    membersCollectionView
                    Spacer()
                }
                .padding(.bottom, 40)
                moreActionSheetView
            }
        }
        
        //MARK: - Views
        var membersCollectionView: some View {
            ScrollView {
                LazyVGrid(
                    columns: spaceViewModel.memberColumns,
                    alignment: .leading,
                    spacing: 16,
                    pinnedViews: [.sectionHeaders, .sectionFooters]
                ) {
                    ForEach(spaceViewModel.space.members, id: \.self) { member in
                        SpaceMemberCell(member: member, action: spaceViewModel.spaceMemberCellTapped(_:))
                    }
                }
                .padding([.leading, .trailing], 20)
            }
        }
    }

空间视图模型

    class SpaceViewModel: ObservableObject {
        @Published var space: Space
        
        @Published var showAddFriendsActionSheet = false
        @Published var showMoreButton: Bool = true
        @Published var showMusicButton: Bool = false
        @Published var showAddFriendsButton: Bool = true
        @Published var showRaiseHandButton: Bool = false
        @Published var showMuteButton: Bool = false
        @Published var memberColumns: [GridItem] = []
        @Published var selectedMember: SpaceMember?
        @Published var accessType: SpaceAccessType = .member
        @Published var memberActionSheetOffset: CGFloat = 0
        @Published var moreActionSheetOffset: CGFloat = 0
        @Published private(set) var isAllMuted: Bool
        //@Published private(set) var roomStatus: Space.RoomStatus
        private var spaceListener: ListenerRegistration!
        @Published var isKickedOut = false
        
        init(space: Space) {
            self.space = space
            self.isAllMuted = space.isAllMuted
            self.roomStatus = space.roomStatus
            self.memberColumns = Array(repeating: GridItem(.fixed(100), spacing: 16), count: space.members.count)
            setAccessType()
        }
        
        deinit {
            removeListeners()
        }
        
        ///initializer for personal/solo space
        init(personalSpace: Space) {
            self.space = personalSpace
            self.isAllMuted = personalSpace.isAllMuted
            self.roomStatus = personalSpace.roomStatus
            setAccessType()
            self.showMuteButton = false
        }
        
        func removeListeners() {
            if spaceListener != nil {
                spaceListener.remove()
            }
        }
        
        func setAccessType(){
            guard let userId = Customer.current?.userId else { return }
            if space.owner.memberInfo.userId == userId {
                accessType = .owner
            } else if space.speakerIds.contains(where: { $0 == userId }) { //check if current user is one of the speakerIds
                accessType = .speaker
            }
            switch accessType {
            case .owner:
                showMusicButton = true
                showRaiseHandButton = false
                showMuteButton = true
                
            case .speaker:
                showRaiseHandButton = true
                showMuteButton = true
                showMusicButton = false
                
            case .member:
                showRaiseHandButton = true
                showMuteButton = false
                showMusicButton = false
            }
        }
        
        func updateIsAllMuted(shouldMute: Bool) {
            let newSpace = space
            isAllMuted = shouldMute
            SpaceService.updateIsAllMuted(isAllMuted: shouldMute, spaceId: space.spaceId)
            newSpace.updateIsAllMuted(shouldMute)
            space = newSpace
        }
        
        func startSpaceListener() {
            spaceListener = db.collection(CollectionKeys.spaces)
                .document(space.spaceId)
                .addSnapshotListener({ (snapshot, error) in
                    if let error = error {
                        print("Error on space listener \(error.localizedDescription)")
                        self.handleError(title: "Error fetching space", message: error.localizedDescription)
                        return
                    }
                    guard let snapshot = snapshot,
                          let newSpace = Space(document: snapshot)
                    else {
                        print("Failed to create a space in listener")
                        return
                    }
                    self.space = newSpace
                    let memberIds = newSpace.members.map({$0.userId})
                    if !memberIds.contains(Customer.current!.userId) {
                        **//kick out user here or something**
                    }
                })
        }
        
        func spaceMemberCellTapped(_ member: SpaceMember) {
            selectedMember = member
            memberActionSheetOffset = 0
        }

        func removeFromSpace() {
            guard let member = selectedMember else { return }
            SpaceService.removeMember(member: member, spaceId: space.spaceId) { (alertError) in
                if let alertError = alertError {
                    print("Error toggling space status \(alertError)")
                    //self.handleAlertError(alertError: alertError)
                    return
                }
                self.space.removeMember(member: member)
            }
            selectedMember = nil
            memberActionSheetOffset = UIScreen.main.bounds.height
        }
    }

SpaceViewModelstartSpaceListener() 中,如果用户的userId 不在空间列表中,我想关闭SpaceViewSpaceSpaceMemberSpaceOwner 只是一个没有任何装饰器的简单类。

我认为没有必要,但我可以根据要求提供模型的代码。

谢谢你:)

【问题讨论】:

    标签: swift firebase google-cloud-firestore swiftui


    【解决方案1】:

    我认为您需要在内部将isKickedOut 设置为true

        if !memberIds.contains(Customer.current!.userId) {
            isKickedOut = true 
        }
    

    那么在这部分

        ForEach(spaceViewModel.space.members, id: \.self) { member in
                            SpaceMemberCell(member: member, action: spaceViewModel.spaceMemberCellTapped(_:))
    }
    

    检查spaceViewModel.isKickedOut 是否为false,仅在这种情况下返回SpaceMemberCells

    喜欢:

        if !spaceViewModel.isKickedOut {
            ForEach(spaceViewModel.space.members, id: \.self) { member in
                                SpaceMemberCell(member: member, action: spaceViewModel.spaceMemberCellTapped(_:))
        }
     }
    

    【讨论】:

    • 抱歉,但我希望使用 NavigationLink 关闭前一个视图显示的 SpaceView,这就是为什么我想以某种方式调用presentationMode.wrappedValue.dismiss()
    • 在 swift UI 中,我们使用声明式方法来构建用户界面,因此,您需要声明何时在前一个视图中显示 SpaceView,如果此条件不正确,则不再显示它。在这种情况下,我不认为使用命令式解雇是正确的做法......
    • 我会记住这一点,但我很难理解如何做到这一点。我目前正在使用NavigationLink(destination: SpaceView(space: space), isActive: showSpaceView){ EmptyView() } 来展示带有动画的 SpaceView。不知道 SpaceView 如何使 showSpaceView = false
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-08
    • 1970-01-01
    • 2020-07-27
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    相关资源
    最近更新 更多