Crash when disabling scroll before calling ObjC Syntax Highlighter
I've got a project that involves highlighting a custom syntax I've created. The highlighting happens on
textview_did_change()in the delegate of a
ui.TextView()that is a subview of the main view, which is a
When editing more than one screenful of text, the rewrite of the
NSMutableAttributedStringto the TextView moves the cursor to the end of the file briefly and, depending on view position, can cause the view to scroll away from the editing point. To mitigate this, I've attempted to disable scrolling before the call to the syntax highlighter, and re-enable it afterwards. I also save the cursor position and restore it. I'm not sure I've gone about all of this in the cleanest possible way, but it works.
The problem is that it crashes if a second subview is added to the main view using
add_subview(). I discovered this is the trigger only by commenting out code until I isolated it. I get no ObjectiveC exception log in the folder to give me a clue to what is going wrong.
I've posted a minimal example at https://github.com/nbeversl/pythonista-crash-min-example.
syntax.pyis the code for the highlighting that I'm using in the project.
main.pyis a minimal example that reproduces the problem.
The example works as is. To see the crash, uncomment line 84 and then try typing text into the textview.
Adding subviews works fine (no crashes) if the scrolling behavior is not changed before and after the update.
Is there another way to prevent the scrolling/cursor positioning issues when calling the highlighting, or if not, what is the interaction between that and the secondary subview that causes the crash and how to fix?
The main project has about 8 subviews ; adding any one of them causes this crash.
@nfmusician, I cannot dig in deeper right now, but just a thought: could you have two views, always updating, repositioning and edit-enabling the one that is not visible, then bringing it forward?
Another idea might be to use a MutableAttributedString, and modify it in place?
I notice that when you disable scrolling, you are not setting that on the main_thread. All ui properties should be set using on_main_thread -- I think pythonista takes care of some of that in the ui module itself, but probably not every property.
Have you looked at the objc exception handler traceback? Sometimes there is a useful message that can provide some insight.
By the way, if your syntax is expressible as a cascaded set of regex, you might consider using the built in syntax highlighter, which could be used in textviews, I think (or OMTextViews?)
Initial investigations of modifying the syntax highlighter for the editor itself
@JonB I was not aware of the built-in syntax highlighter and so built my own from scratch, basically following a train of thought from these two threads and using
objc_util: https://forum.omz-software.com/topic/2727/ui-textview-individual-words and https://forum.omz-software.com/topic/2014/beta-tinkering-with-pythonista-s-internals-using-objc_util/15. I checked the Pythonista site and a Google search for "OMTextView" and "OMSyntaxHighlighter" but can find nothing except passing references. Is this documented, or is this just something under the hood I'll have to investigate?
My custom syntax is indeed expressible as nested RegEx, which is essentially how I've implemented it myself (https://github.com/nbeversl/pythonista-crash-min-example/blob/master/syntax.py).
As a result of creating the "minimal example" for this thread, I discovered -- entirely by accident --that this crash is eliminated if the
ui.TextViewis instantiated before any subviews are added to the main view (the parent of the
ui.TextView, which is a
ui.View). After that, calling
add_subview()through the (non-Objective-C)
uimodule API on the main view works -- and the disabling/re-enabling of the scrolling described above also works.
I'm happy for the moment with any solution that gets my main project working, but at the same time I'm curious what I may not be understanding here -- is there something about an
ObjCInstanceof a view that interacts poorly with non-
ObjCinstancesibling views, or is interfered with by changes to the parent view?