Re: unable to update UI on main thread in 10.13
Re: unable to update UI on main thread in 10.13
- Subject: Re: unable to update UI on main thread in 10.13
- From: sqwarqDev <email@hidden>
- Date: Fri, 27 Oct 2017 21:17:05 +0700
> On 27 Oct 2017, at 21:11, David Duncan <email@hidden> wrote:
>
> In your background task which attributed string are you modifying? From the
> looks of your ‘updateUI’ function it seems like you are modifying the one
> that NSTextView provides, which is likely to actually be an instance of
> NSTextStorage and sending callbacks to the NSTextView to update itself –
> which would trigger drawing on your background thread.
>
> In general however, I would recommend a different approach to your processing
> – have your background task work on its own local mutable attributed string,
> then signal that string back to the main thread when it is done. This should
> also allow you to avoid the time you use to poll the completion of this work
> (since you’ll be told specifically when the work is finished, rather than
> having to check a progress flag).
>
Thanks for the reply, David.
Hmm, interesting that you say that. The ‘superAttributedString’ was precisely
meant to avoid the problem you’re suggesting in my last code refactor. It’s
declared in the ViewController as global var. The textview isn’t supposed to
know anything about it till it gets sent it in the last line of the updateUI
func.
What made you think that it comes from the textview?
>> On Oct 27, 2017, at 7:03 AM, sqwarqDev <email@hidden> wrote:
>>
>> I have a subclass of NSTextView which I'm trying to update in my UI. When
>> the user clicks a button in the main UI, I run a bunch of processes in the
>> background, save their output to an attributed string, then update the
>> textview's textstorage on the main thread using
>> performSelector(onMainThread:).
>>
>> @IBAction func profileAction(_ sender: Any)
>> {
>> <background stuff that appends text to a string, then wait till
>> it's all done with repeat timer >...
>> this_timer = Timer.scheduledTimer(timeInterval: 1.0, target:
>> self, selector: #selector(self.myRepeatFunc),userInfo: nil, repeats: true)
>> this_timer.fire()
>> }
>>
>>
>> @objc func myRepeatFunc()
>> {
>> if stuffIsDone == true
>> {
>> this_timer.invalidate()
>> self.scanBtn.isEnabled = true
>> self.profileBtn.isEnabled = true
>> self.historyBtn.isEnabled = true
>> performSelector(onMainThread: #selector(updateUI), with: nil,
>> waitUntilDone: false)
>> }
>> }
>>
>>
>> @objc func updateUI()
>> {
>>
>> let zeroAttributesString = NSMutableAttributedString(string: "")
>>
>> self.profilerTextView.textStorage?.setAttributedString(zeroAttributesString)
>>
>> self.profilerTextView.textStorage?.setAttributedString(self.superAttributedString)
>> }
>>
>>
>> This works absolutely fine in both 10.11 and 10.12; however, on 10.13 I get
>> the dreaded "This application is modifying the autolayout engine from a
>> background thread after the engine was accessed from the main thread. This
>> can lead to engine corruption and weird crashes." message.
>>
>> I've tried swapping out performSelector(onMainThread:) for
>> DispatchQueue.main.async to no avail. I still get the same error. I've tried
>> using Xcode 9's 'Main Thread Checker' diagnostic tool, but even though I
>> have 'Pause on issues' selected, it never pauses and just lets my code run.
>> I've also tried symbolic breakpoints on [NSView setFrame] and
>> _AssertAutolayoutOnAllowedThreadsOnly from the stack trace. Neither stop my
>> code.
>>
>> I'm out of ideas, and the rubber duck has come up short. Any advice much
>> appreciated (stack trace follows):
>>
>> This application is modifying the autolayout engine from a background thread
>> after the engine was accessed from the main thread. This can lead to engine
>> corruption and weird crashes.
>> Stack:(
>> 0 Foundation 0x00007fff51ccc87a
>> _AssertAutolayoutOnAllowedThreadsOnly + 201
>> 1 Foundation 0x00007fff51cccf0d -[NSISEngine
>> _optimizeIfNotDisabled] + 25
>> 2 Foundation 0x00007fff51a526f4 -[NSISEngine
>> constraintDidChangeSuchThatMarker:shouldBeReplacedByMarkerPlusDelta:] + 173
>> 3 Foundation 0x00007fff51a52572 -[NSISEngine
>> tryToChangeConstraintSuchThatMarker:isReplacedByMarkerPlusDelta:undoHandler:]
>> + 312
>> 4 Foundation 0x00007fff51a46320
>> -[NSLayoutConstraint _tryToChangeContainerGeometryWithUndoHandler:] + 484
>> 5 Foundation 0x00007fff51a42eaa
>> -[NSLayoutConstraint _setSymbolicConstant:constant:] + 311
>> 6 Foundation 0x00007fff51a42d45
>> -[NSLayoutConstraint setConstant:] + 68
>> 7 AppKit 0x00007fff4da9e7a0
>> -[NSView(NSConstraintBasedLayout)
>> _updateSimpleAutoresizingConstraintsInPlace:forAutoresizingMask:] + 1501
>> 8 AppKit 0x00007fff4da9ea35
>> NSViewUpdateConstraintsForFrameChange + 441
>> 9 AppKit 0x00007fff4cfa4599 -[NSView
>> setFrameSize:] + 1515
>> 10 AppKit 0x00007fff4cfbaa52 -[NSView
>> setFrame:] + 371
>> 11 AppKit 0x00007fff4cf70e33 -[NSClipView
>> _updateOverhangSubviewsIfNeeded] + 839
>> 12 AppKit 0x00007fff4d04050d -[NSClipView
>> _reflectDocumentViewFrameChange] + 692
>> 13 AppKit 0x00007fff4cfaa1b0 -[NSView
>> _postFrameChangeNotification] + 83
>> 14 AppKit 0x00007fff4cfa47bb -[NSView
>> setFrameSize:] + 2061
>> 15 AppKit 0x00007fff4d03a23b
>> -[NSTextView(NSPrivate) _setFrameSize:forceScroll:] + 1081
>> 16 AppKit 0x00007fff4d039d3a -[NSTextView
>> setFrameSize:] + 143
>> 17 AppKit 0x00007fff4d0392ac -[NSTextView
>> setConstrainedFrameSize:] + 635
>> 18 UIFoundation 0x00007fff72e25084
>> -[NSLayoutManager(NSPrivate) _resizeTextViewForTextContainer:] + 938
>> 19 UIFoundation 0x00007fff72f392d6
>> _resizeTextViewsIfNeeded + 285
>> 20 UIFoundation 0x00007fff72e29ea2
>> _NSFastFillAllLayoutHolesForGlyphRange + 1851
>> 21 UIFoundation 0x00007fff72e6890b
>> -[NSLayoutManager lineFragmentRectForGlyphAtIndex:effectiveRange:] + 39
>> 22 AppKit 0x00007fff4d1071de -[NSTextView
>> _extendedGlyphRangeForRange:maxGlyphIndex:drawingToScreen:] + 509
>> 23 AppKit 0x00007fff4d0d69fc -[NSTextView
>> drawRect:] + 1807
>> 24 AppKit 0x00007fff4d82ee3d
>> _NSViewDrawRect + 83
>> 25 AppKit 0x00007fff4d83c0d4
>> -[NSView(NSInternal)
>> _recursive:displayRectIgnoringOpacity:inGraphicsContext:shouldChangeFontReferenceColor:]
>> + 1578
>> 26 AppKit 0x00007fff4d83baa4
>> -[NSView(NSInternal)
>> _recursive:displayRectIgnoringOpacity:inContext:shouldChangeFontReferenceColor:]
>> + 56
>> 27 AppKit 0x00007fff4d0ce374
>> __46-[NSView(NSLayerKitGlue) drawLayer:inContext:]_block_invoke + 289
>> 28 AppKit 0x00007fff4d0cdf08
>> -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] +
>> 1577
>> 29 AppKit 0x00007fff4d0cd8d9
>> -[NSView(NSLayerKitGlue) drawLayer:inContext:] + 77
>> 30 AppKit 0x00007fff4d272cbc -[NSTextView
>> drawLayer:inContext:] + 114
>> 31 AppKit 0x00007fff4d1ef863
>> -[_NSBackingLayerContents drawLayer:inContext:] + 165
>> 32 QuartzCore 0x00007fff5aa50b76 -[CALayer
>> drawInContext:] + 281
>> 33 AppKit 0x00007fff4d1ef44d
>> -[_NSTiledLayer drawTile:inContext:] + 634
>> 34 AppKit 0x00007fff4d1ef179
>> -[_NSTiledLayerContents drawLayer:inContext:] + 181
>> 35 QuartzCore 0x00007fff5aa50b76 -[CALayer
>> drawInContext:] + 281
>> 36 AppKit 0x00007fff4d1ef0b9
>> -[NSTileLayer drawInContext:] + 166
>>
>>
>>
>> TIA
>>
>>
>> Best
>>
>>
>>
>> Phil
>> @sqwarq
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
> --
> David Duncan
>
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden