Maintaining NSTextView Insertion Point After Core Data Save
I am working on a Mac journaling application that uses Core Data. The user interface consists of a table view and a text view. The table view contains a list of dates. Selecting a date fills the text view with what was written on that date. Use the text view to write.
One problem I had was saving the text. Core Data is set up initially to save a text view or text field’s contents only when leaving the text view or text field. This behavior works fine for a contact form, but not for a journaling application. Core Data would save the text only when I selected a new date in the table view. With this behavior there’s potential for data loss.
I wrote some code to autosave the text view’s contents periodically. The saving worked, but every time I saved, the text view lost focus. When the text view lost focus, I had to click in the text view to resume typing. Autosaving provided a miserable typing experience. How could I autosave while allowing someone to keep typing? I had to perform the following steps:
- Call the
NSTextViewfunctionselectedRangeto save where the person was typing during the autosave. - Call the
NSWindowfunctionmakeFirstResponderto make the text view the first responder so the text view didn’t lose focus. - Call the
NSTextViewfunctionsetSelectedRangeto set the typing position back to where it was before the autosave. - Call the
NSTextfunctionscrollRangeToVisibleto make the text view scroll to the point where the person was typing.
Here’s some Swift 3 code.
func updateTextViewAfterAutosave() {
let insertionRange = textView.selectedRange()
window.makeFirstResponder(textView)
textView.setSelectedRange(insertionRange)
textView.scrollRangeToVisible(insertionRange)
}
Make sure you don’t autosave too often. When I used this code to autosave after every change to the text view’s contents, the text view scrolling was visibly jumpy. Autosaving every 30 seconds worked well.