translation
www.hackingwithswift.com/books/ios-s…


For more content, please follow the public account “Swift Garden”.


Like articles? How about 🔺💛➕ company 3? Follow this column, follow me 🚀🚀🚀

Removes objects from a Core Data Fetech request

We’ve already used @fetchRequest to pull Core Data objects into SwiftUI’s List, and with a little more work, we can enable the swipe delete and Edit/Finish buttons.

As with regular data arrays, most of the work is done by attaching an onDelete(perform:)modifier to ForEach, but instead of removing items from the array, we need to find the requested object from the fetch request, We then call our managed Object Context’s delete() method on it. Once the target objects are all deleted, we need to trigger the saving of the context. If you do not, the changes will not actually be written to disk.

Add the following method to the ContentView:

func deleteBooks(at offsets: IndexSet) {
    for offset in offsets {
        // find this book in our fetch request
        let book = books[offset]

        // delete it from the context
        moc.delete(book)
    }

    // save the context
    try? moc.save()
}Copy the code

Note that onDelete(perform:)modifier is attached to the ForEach modifier instead of the List.

Add the following modifier:

.onDelete(perform: deleteBooks)Copy the code

Now that we’ve got the swipe delete feature, we can go one step further and add an Edit/finish button. Go to the navigationBarItems()modifier for ContentView and change it to the following:

.navigationBarItems(leading: EditButton(), trailing: Button(action: {Copy the code

Now that the ContentView is complete, try running the app again — you should be free to add and remove books, with the deletion triggered by swiping a gesture or editing a button.

translation
www.hackingwithswift.com/books/ios-s…

Display NavigationLink with alert

NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink NavigationLink Because we’re in a NavigationView, iOS automatically provides a “Back” button that lets the user go Back to the previous screen, and they can also be swiped Back from the left edge of the screen. However, it is sometimes useful to return programmatically.

To demonstrate this, we’ll add one last feature to our application: delete the book the user is reading. To do this, we need to display a warning box indicating whether the user really wants to delete the book, and then delete it from the current Managed Object Context. Once this is done, there is no point in staying on the current screen because the associated book no longer exists. We need to pop up the current view — remove it from the top of the NavigationView stack and return to the previous screen.

First, we need three new properties in the DetailView structure: One holds the Core Data managed Object Context (so we can delete things), one holds the Presentation mode (so we can pop the view from the navigation stack), and one controls whether we want to display the status of the confirmation warning.

Add the following three properties to the DetailView:

@Environment(\.managedObjectContext) var moc
@Environment(\.presentationMode) var presentationMode
@State private var showingDeleteAlert = falseCopy the code

The second step is to write a method that removes the current book, and then dismiss the current view. As to the view through the navigation link rather than a sheet shows this distinction, we can still use the same presentationMode. WrappedValue. Dismiss () code.

Add the following method to the DetailView:

func deleteBook(a) {
    moc.delete(book)

    // uncomment this line if you want to make the deletion permanent
    // try? self.moc.save()
    presentationMode.wrappedValue.dismiss()
}Copy the code

The third step is to add an Alert ()modifier that follows showingDeleteAlert and displays an alert view internally that asks the user to confirm the action. So far we have used a simple alert with a dimiss button. This time we need two buttons: one to delete the book and one to cancel.

SwiftUI provides two specialized buttons for this purpose:.destructive receives the title and action closure, which appears red to warn the user that the action will delete data, and.cancel() causes the alert to be dismisse. Apple provides clear guidelines on how we should label alert text, so let me reiterate them here: “OK” is fine if it’s something as simple as “I understand”, but if you want the user to make a choice, you should avoid headings like “Yes” and “No” and use verbs like “Ignore”, “Reply” and “Confirm” instead.

In this case, we’ll have “Delete” as the title of the Destructive buttons, followed by a.cancel() button so that the user can exit the Delete operation. Add the following modifier to the DetailView’s GeometryReader:

.alert(isPresented: $showingDeleteAlert) {
    Alert(title: Text("Delete book"), message: Text("Are you sure?"), primaryButton: .destructive(Text("Delete")) {
            self.deleteBook()
        }, secondaryButton: .cancel()
    )
}Copy the code

The final step is to add a navigation bar button to start the delete process — it does only one thing, reverse the showingDeleteAlert Boolean, because alert()modifier is already monitoring it. Add the following modifier to the DetailView’s GeometryReader as well:

.navigationBarItems(trailing: Button(action: {
    self.showingDeleteAlert = true{})Image(systemName: "trash")})Copy the code

Now you can delete the book using the swipe or edit button in the ContentView, or you can do the same by clicking the special delete button in the DetailView view — it deletes the book, updates the ContentView list, and automatically closes the current DetailView.

Another app is complete – well done!


My official account here Swift and computer programming related articles, as well as excellent translation of foreign articles, welcome to pay attention to ~