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.
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:
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