@@ -19,6 +19,8 @@ There is an Example app available [here](https://github.com/mdb1/ViewStateContro
1919 * [ Changing Loading types] ( https://github.com/mdb1/ViewStateController#changing-loading-types )
2020 * [ Using Custom Views] ( https://github.com/mdb1/ViewStateController#using-custom-views )
2121 * [ Demo] ( https://github.com/mdb1/ViewStateController#demo-loading-type-options )
22+ * [ ModifyingIds] ( https://github.com/mdb1/ViewStateController#modifying-ids )
23+ * [ Demo] ( https://github.com/mdb1/ViewStateController#demo-modifying-ids )
2224* [ Toasts] ( https://github.com/mdb1/ViewStateController#toast )
2325 * [ Examples with code samples] ( https://github.com/mdb1/ViewStateController#examples-with-code-samples-1 )
2426
@@ -283,6 +285,80 @@ In this video, we are tweaking around some properties and pass them to the `with
283285
284286The app used for this video can be downloaded from [ this repository] ( https://github.com/mdb1/ViewStateControllerExampleApp ) .
285287
288+ ## Modifying Ids
289+
290+ The ViewStateController object also provided an array of Strings (modifyingIds):
291+
292+ ``` swift
293+ /// Use this property when you need to make changes to specific parts of your view.
294+ /// Example: When you want to display a ProgressView while deleting an item from a list.
295+ public var modifyingIds: [String ]?
296+ ```
297+
298+ It's usage is really simple:
299+
300+ ``` swift
301+ func listView (_ pokemons : [Pokemon]) -> some View {
302+ VStack {
303+ ForEach (pokemons) { pokemon in
304+ HStack {
305+ Text (pokemon.name )
306+ Spacer ()
307+ trailingView (for : pokemon.id )
308+ }
309+ Divider ()
310+ }
311+ }
312+ }
313+
314+ @ViewBuilder
315+ func trailingView (for id : String ) -> some View {
316+
317+ if let modifyingIds = controller.modifyingIds, modifyingIds.contains (id) {
318+ // If the id is in the `modifyingIds` array, it means someone is modifying it.
319+ // So we display a loading indicator.
320+ ProgressView ()
321+ } else {
322+ // Otherwise, we display a remove button.
323+ Button (" Remove" , role : .destructive ) {
324+ Task {
325+ // Tapping the button triggers an async call to remove the pokemon.
326+ await removePokemon (id : id)
327+ }
328+ }
329+ }
330+ }
331+
332+ func removePokemon (id : String ) async {
333+ withAnimation {
334+ // We add the `id` to the array.
335+ controller.modifyingIds = (controller.modifyingIds ?? []) + [id]
336+ }
337+ // We simulate an async call to the backend. (1 second sleep)
338+ try ? await Task.sleep (nanoseconds : 1_000_000_000 )
339+ if let latestInfo = controller.latestInfo {
340+ let updatedInfo = latestInfo.filter { pokemon in
341+ pokemon.id != id
342+ }
343+ withAnimation {
344+ // Then we update the state
345+ controller.setState (.loaded (updatedInfo))
346+ // And remove the id from the modifying array
347+ controller.modifyingIds ? .removeAll (where : { $0 == id })
348+ }
349+ }
350+ }
351+
352+ struct Pokemon : Identifiable {
353+ let id: String
354+ let name: String
355+ }
356+ ```
357+
358+ ### Demo: Modifying Ids
359+
360+ https://user-images.githubusercontent.com/5333984/225748007-ff1e0fed-8e80-4b73-9f3e-d83b7edc3064.mov
361+
286362# Toasts
287363
288364Similar to the LoadingModifier, there is also a [ ToastModifier] ( https://github.com/mdb1/ViewStateController/blob/main/Sources/ViewStateController/ViewModifiers/ToastModifier.swift ) that let's you present toast/snack bars/custom views in the screen with a set of configurable parameters.
0 commit comments