Making an editable Label with SwiftUI

Let’s say you’re showing the user a list of sidebar selectable categories. These categories appear on the sidebar as SwiftUI Labels and, depending on the one selected, the app will show one view or another.

Screen Shot 2022 01 05 at 12 45 24 PM

So far, so good… But what if the user would like to rename one of the categories?

Ideally Label would have a property to allow us to put it in edit mode. However, as of Jan 2022, that property does not exist.

With that in mind, we could pursue one of several options:

     a) Linking to an AppKit / UIKit library

     b) Using alerts

     c) Implementing it using a combination of SwiftUI classes

I went with the latter, as it seemed the cleanest approach. Here’s the result I came up with: 

QuickDemoEditLabel

In a nutshell: it’s a view that by default shows a Label and, when ‘edit mode’ is turned on, becomes a TextView. When the user is done, which is detected by editChanged and commit arguments, changes are saved and the view reverts back to a Label. 

Here’s the code:

struct EditableLabel: View{

    @ObservedObject var tag: Tag

    @State private var editing = false

    @State private var newName: String

 

    init(tag: Tag){

        self.newName = tag.name.bound

        self.tag = tag

    }

    

    var body: some View{

        if editing == true{

            TextField(“”, text: $newName, onEditingChanged: {editChanged in

                if editChanged == true{

                    //Focused

                }else{

                    //Lost focus, catches return or when user taps away

                    editing = false

                    tag.name = newName

                }

            }, onCommit: {

                //Catches escape

                editing = false

                tag.name = newName

            })

        }else{

            Label(tag.name ?? “”, systemImage: “tag”)

            .contextMenu {

                Button{

                    editing = true

                } label: {

                    Label(“Rename Tag”, systemImage: “tag”)

                }

 

            }

        }

    }

}

 

In the above example the view is connected to a CoreData class, same approach could be used with tweaks to link it to any other model. 

Thoughts / suggestions? You can reach me @MarcMasVi

Until next time, 

Marc