Reputation: 119
I'm using ToolbarContent with ToolbarItem to have consistent toolbars across multiple views... The Toolbar looks like:
struct ToolBarCancelDeleteAdd: ToolbarContent {
@Binding var deletePressed: Bool
let cancel: () -> Void
let deleting: () -> Void
let adding: () -> Void
var body: some ToolbarContent {
ToolbarItemGroup(placement: .cancellationAction) {
Button("Cancel", action: cancel )
}
ToolbarItemGroup(placement: .confirmationAction) {
if deletePressed {
Button(action: deleting, label:{Text("Done")})
} else {
Button(action: deleting, label:{Text("Delete")})
}
Button(action: adding, label: {Image(systemName: "plus")})
}
}
In my view I'm adding the toolbar and providing the closure information needed..
.navigationBarBackButtonHidden(true)
.navigationTitle("Budget Descriptions")
.toolbar() {
ToolBarCancelDeleteAdd(deletePressed: $deletePressed){
if self.editMode?.wrappedValue == .active {
self.editMode?.wrappedValue = .inactive
deletePressed.toggle()
}
self.presentationMode.wrappedValue.dismiss()
} deleting: {
if self.editMode?.wrappedValue == .inactive {
self.editMode?.wrappedValue = .active
deletePressed.toggle()
} else {
self.editMode?.wrappedValue = .inactive
deletePressed.toggle()
}
} adding: {
if self.editMode?.wrappedValue == .active {
self.editMode?.wrappedValue = .inactive
}
self.isAdding.toggle()
}
} // END OF TOOLBAR
This all works very fine and I'm happy with it..... except I'm doing this code across multiple views and if I needed to tweak it I have to go to multiple views to tweak it. It would be great if I could name this closure content like I have done with some views using ViewBuilder. This way I could just name the closure content some way.. Like...
.navigationBarBackButtonHidden(true)
.navigationTitle("Budget Descriptions")
.toolbar() {
ToolBarCancelDeleteAdd(deletePressed: $deletePressed){
CancelContent()
} deleting: {
DeleteContent()
} adding: {
AddingContent()
}
} // END OF TOOLBAR
Upvotes: 0
Views: 336
Reputation: 119
With the suggestion of Nigel Gee above and the help of Javier of SwiftUI Lab I have my final solution to my goal of being able to inject the code into my .toolbar. It looks like:
class ToolbarViewModel: ObservableObject {
func cancelContent(editMode: Binding<EditMode>?) {
if editMode?.wrappedValue == .active {
editMode?.wrappedValue = .inactive
}
}
func deleteContent(deletePressed: inout Bool, editMode: Binding<EditMode>?) {
if editMode?.wrappedValue == .inactive {
editMode?.wrappedValue = .active
} else {
editMode?.wrappedValue = .inactive
}
}
func addingContent(isAdding: inout Bool, editMode: Binding<EditMode>?) {
if editMode?.wrappedValue == .active {
editMode?.wrappedValue = .inactive
}
isAdding.toggle()
}
}
In my View I declare:
@Environment(\.editMode) var editMode: Binding<EditMode>?
@StateObject var toolbarViewModel = ToolbarViewModel()
and the toolbar looks like:
.toolbar {
ToolBarCancelDeleteAdd() {
toolbarViewModel.cancelContent(editMode: editMode)
presentationMode.wrappedValue.dismiss()
} deleting: {
toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: editMode)
} adding: {
toolbarViewModel.addingContent(isAdding: &isAdding, editMode: editMode)
}
} // END OF TOOLBAR
Upvotes: 1
Reputation: 123
Why not make a class that hold the methods
class ToolbarViewModel: ObservableObject {
func cancelContent(deletePressed: inout Bool, editMode: inout EditMode) {
if editMode == .active {
editMode = .inactive
deletePressed.toggle()
}
}
func deleteContent(deletePressed: inout Bool, editMode: inout EditMode) {
if editMode == .inactive {
editMode = .active
deletePressed.toggle()
} else {
editMode = .inactive
deletePressed.toggle()
}
}
func addingContent(isAdding: inout Bool, editMode: inout EditMode) {
if editMode == .active {
editMode = .inactive
}
isAdding.toggle()
}
}
then you can use this at call
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode
@StateObject var toolbarViewModel = ToolbarViewModel()
@State private var deletePressed = false
@State private var isAdding = false
@State private var editMode: EditMode = .active
var body: some View {
NavigationView {
VStack {
Text("Hello, world!")
.padding()
}
.toolbar {
ToolBarCancelDeleteAdd(deletePressed: $deletePressed) {
toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: &editMode)
presentationMode.wrappedValue.dismiss()
} deleting: {
toolbarViewModel.deleteContent(deletePressed: &deletePressed, editMode: &editMode)
} adding: {
toolbarViewModel.addingContent(isAdding: &isAdding, editMode: &editMode)
}
}
}
}
}
enum EditMode {
case active, inactive
}
Upvotes: 1