Правильный способ представления ActionSheet с помощью SwiftUI

Я хочу показать ActionSheet (или любой другой модальный, кроме Alert) на каком-то событии, например, нажатии кнопки.

Я нашел способ сделать это с помощью переменной состояния. Мне кажется немного странным отображать его таким образом, потому что мне приходится сбрасывать переменную, когда ActionSheet закрывается вручную.

Есть ли лучший способ сделать это?

Почему существует отдельный метод представления Alert, который позволяет связать его видимость с переменной состояния? Какая разница с моим подходом?

struct Sketch : View {
    @State var showActionSheet = false

    var body: some View {
        ZStack {
            Button(action: { showActionSheet = true }) { Text("Show") }
        }
        .presentation(showActionSheet ?
            ActionSheet(
                title: Text("Action"),
                buttons: [
                    ActionSheet.Button.cancel() { 
                        self. showActionSheet = false 
                    }
                ]) 
        : nil)
    }
}

4 ответа

Обеспечивая предпочтение подхода с использованием переменных состояния, Apple применила API-интерфейсы предупреждений и действий. Для тех, кто нашел этот вопрос, вот обновленные примеры всех 3 типов на основе Xcode 11 beta 7, iOS 13.

@State var showAlert = false
@State var showActionSheet = false
@State var showAddModal = false

var body: some View {
    VStack {
        // ALERT
        Button(action: { self.showAlert = true }) {
            Text("Show Alert")
        }
        .alert(isPresented: $showAlert) {
             // Alert(...)
             // showAlert set to false through the binding
        }

        // ACTION SHEET
        Button(action: { self.showActionSheet = true }) {
            Text("Show Action Sheet")
        }
        .actionSheet(isPresented: $showActionSheet) {
             // ActionSheet(...)
             // showActionSheet set to false through the binding
        }

        // FULL-SCREEN VIEW
        Button(action: { self.showAddModal = true }) {
            Text("Show Modal")
        }
        .sheet(isPresented: $showAddModal, onDismiss: {} ) {
            // INSERT a call to the new view, and in it set showAddModal = false to close
            // e.g. AddItem(isPresented: self.$showAddModal)
        }
}

Для модальной части вашего вопроса, вы можете использовать PresentationButton:

struct ContentView : View {
    var body: some View {
        PresentationButton(Text("Click to show"), destination: DetailView())
    }
}

Источник

struct Sketch : View {
    @State var showActionSheet = false

    var body: some View {
    ZStack {
        Button(action: { self.showActionSheet.toggle() }) { Text("Show") }
            .actionSheet(isPresented: $showActionSheet) {
                ActionSheet(title: Text("Test"))
            }
        }
    }
}

Это сработает, @State - это оболочка свойств, и ваш лист действий будет следить за ним, всякий раз, когда он превращается в true, лист действий будет отображаться

Ниже приведен лучший способ показать несколько листов действий в соответствии с требованиями.

      struct ActionSheetBootCamp: View {

@State private var isShowingActionSheet = false
@State private var sheetType: SheetTypes = .isOtherPost

enum SheetTypes {
    case isMyPost
    case isOtherPost
}

var body: some View {
    HStack {
        Button("Other Post") {
            sheetType = .isOtherPost
            isShowingActionSheet.toggle()
        }
        Button("My post") {
            sheetType = .isMyPost
            isShowingActionSheet.toggle()
        }
    }.actionSheet(isPresented: $isShowingActionSheet, content: getActionSheet)
}

func getActionSheet() -> ActionSheet {
    
    let btn_share: ActionSheet.Button = .default(Text("Share")) {
        //Implementation
    }
    let btn_report: ActionSheet.Button = .destructive(Text("Report")) {
        //Implementation
    }
    let btn_edit: ActionSheet.Button = .default(Text("Edit")) {
        //Implementation
    }
    let btn_cancel: ActionSheet.Button = .cancel()
    switch(sheetType) {
    case .isMyPost:
        return ActionSheet(title: Text("This is the action sheet title"), message: nil, buttons: [btn_share,btn_edit, btn_cancel])
    case .isOtherPost:
        return ActionSheet(title: Text("This is the action sheet title"), message: nil, buttons: [btn_share,btn_report, btn_cancel])
    }
    
}
}
Другие вопросы по тегам