SwiftUI Decode HTML Entities Error: одновременный доступ к 0x7ff43ff29b50, но для модификации требуется эксклюзивный доступ

Я получаю сообщение об ошибке при декодировании html-элементов с помощью NSAttributedString. Я использую Swift 5. Я хочу только html для строки. Мне не нужен веб-просмотр.

Текст SwiftUI

Text("It&#39s a party!".decoded)

Расширение строки

extension String {
    var decoded: String {
        let attr = try? NSAttributedString(data: Data(utf8), options: [
        .documentType: NSAttributedString.DocumentType.html,
        .characterEncoding: String.Encoding.utf8.rawValue
    ], documentAttributes: nil)

        return attr?.string ?? self
    }
}

Журнал ошибок

== AttributeGraph: cycle detected through attribute 123464 ===
=== AttributeGraph: cycle detected through attribute 143224 ===
=== AttributeGraph: cycle detected through attribute 128744 ===
Simultaneous accesses to 0x7ff43ff29b50, but modification requires exclusive access.
Previous access (a modification) started at SwiftUI`LayoutComputer.EngineDelegate.spacing() + 44 (0x7fff566b85dc).
Current access (a modification) started at:
0    libswiftCore.dylib                 0x00007fff2f41fe90 swift_beginAccess + 568
1    SwiftUI                            0x00007fff566b85b0 LayoutComputer.EngineDelegate.spacing() + 44
2    SwiftUI                            0x00007fff56657140 accumulateSpacing #1 (ofChild:) in StackLayout.Header.init(layoutContext:proxies:majorAxis:minorAxisAlignment:uniformSpacing:childStorage:capacity:resizeChildrenWithTrailingOverflow:) + 289
3    SwiftUI                            0x00007fff56656bf0 StackLayout.Header.init(layoutContext:proxies:majorAxis:minorAxisAlignment:uniformSpacing:childStorage:capacity:resizeChildrenWithTrailingOverflow:) + 414
4    SwiftUI                            0x00007fff561d9d00 specialized ManagedBufferPointer.init(bufferClass:minimumCapacity:makingHeaderWith:) + 296
5    SwiftUI                            0x00007fff561da140 specialized closure #2 in HVStack.updateLayoutComputer<A>(rule:layoutContext:children:) + 142
6    SwiftUI                            0x00007fff5626cce0 specialized closure #2 in HVStack.updateLayoutComputer<A>(rule:layoutContext:children:) + 41
7    SwiftUI                            0x00007fff56278590 partial apply for specialized closure #2 in HVStack.updateLayoutComputer<A>(rule:layoutContext:children:) + 43
8    SwiftUI                            0x00007fff561da3e0 specialized static LayoutComputerDelegate.update<A>(_:maybeInPlace:create:) + 136
9    SwiftUI                            0x00007fff56139060 specialized StatefulRule<>.updateLayoutComputer<A>(layout:environment:layoutComputers:) + 176
10   SwiftUI                            0x00007fff562692a0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 236
11   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
12   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
13   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
14   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
15   SwiftUI                            0x00007fff56030ec0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 32
16   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
17   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
18   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
19   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
20   SwiftUI                            0x00007fff56438660 DynamicLayoutViewChildGeometry.childGeometries.getter + 53
21   SwiftUI                            0x00007fff56438740 DynamicLayoutViewChildGeometry.updateValue() + 201
22   SwiftUI                            0x00007fff5626e730 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 15
23   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
24   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
25   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
26   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
27   SwiftUI                            0x00007fff55f66120 specialized UnaryChildGeometry.parentSize.getter + 28
28   SwiftUI                            0x00007fff55f66920 specialized UnaryChildGeometry.value.getter + 91
29   SwiftUI                            0x00007fff56035830 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 28
30   SwiftUI                            0x00007fff5605a690 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 20
31   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
32   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
33   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
34   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
35   SwiftUI                            0x00007fff55f66120 specialized UnaryChildGeometry.parentSize.getter + 28
36   SwiftUI                            0x00007fff55f666b0 specialized UnaryChildGeometry.value.getter + 91
37   SwiftUI                            0x00007fff56035830 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 28
38   SwiftUI                            0x00007fff56040ed0 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 20
39   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
40   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
41   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
42   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
43   SwiftUI                            0x00007fff55f66120 specialized UnaryChildGeometry.parentSize.getter + 28
44   SwiftUI                            0x00007fff55f666b0 specialized UnaryChildGeometry.value.getter + 91
45   SwiftUI                            0x00007fff56035830 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 28
46   SwiftUI                            0x00007fff56040ed0 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 20
47   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
48   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
49   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
50   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
51   SwiftUI                            0x00007fff55f66120 specialized UnaryChildGeometry.parentSize.getter + 28
52   SwiftUI                            0x00007fff55f66440 specialized UnaryChildGeometry.value.getter + 91
53   SwiftUI                            0x00007fff56035830 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 28
54   SwiftUI                            0x00007fff5604f800 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 20
55   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
56   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
57   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
58   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
59   SwiftUI                            0x00007fff55f66120 specialized UnaryChildGeometry.parentSize.getter + 28
60   SwiftUI                            0x00007fff55f666b0 specialized UnaryChildGeometry.value.getter + 91
61   SwiftUI                            0x00007fff56035830 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 28
62   SwiftUI                            0x00007fff56040ed0 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 20
63   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
64   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
65   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
66   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
67   SwiftUI                            0x00007fff56030ec0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 55
68   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
69   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
70   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
71   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
72   SwiftUI                            0x00007fff56438660 DynamicLayoutViewChildGeometry.childGeometries.getter + 53
73   SwiftUI                            0x00007fff56438740 DynamicLayoutViewChildGeometry.updateValue() + 201
74   SwiftUI                            0x00007fff5626e730 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 15
75   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
76   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
77   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
78   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
79   SwiftUI                            0x00007fff56030ec0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 55
80   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
81   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
82   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
83   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
84   SwiftUI                            0x00007fff56033ef0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 63
85   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
86   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
87   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
88   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
89   SwiftUI                            0x00007fff568536f0 StyledTextChildGeometry.parentSize.getter + 27
90   SwiftUI                            0x00007fff560324b0 specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 41
91   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
92   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
93   AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
94   AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
95   SwiftUI                            0x00007fff5608cb10 LayoutPositionQuery.localPosition.getter + 22
96   SwiftUI                            0x00007fff5608cbd0 LayoutPositionQuery.updateValue() + 32
97   SwiftUI                            0x00007fff5628dab0 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 15
98   AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
99   AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
100  AttributeGraph                     0x00007fff4be8e654 AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, bool*, long) + 523
101  AttributeGraph                     0x00007fff4be9fcfa AGGraphGetValue + 203
102  SwiftUI                            0x00007fff568cd9e0 AnimatableFrameAttribute.updateValue() + 45
103  SwiftUI                            0x00007fff5628e5c0 partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:) + 15
104  AttributeGraph                     0x00007fff4be8952a AG::Graph::UpdateStack::update() + 505
105  AttributeGraph                     0x00007fff4be89a6a AG::Graph::update_attribute(AG::data::ptr<AG::Node>, bool) + 335
106  AttributeGraph                     0x00007fff4be91884 AG::Subgraph::update(unsigned int) + 781
107  SwiftUI                            0x00007fff5693a5f0 GraphHost.runTransaction() + 186
108  SwiftUI                            0x00007fff5640e3c0 ViewGraph.updateOutputs(at:) + 90
109  SwiftUI                            0x00007fff5689a880 closure #1 in ViewRendererHost.render(interval:updateDisplayList:) + 1305
110  SwiftUI                            0x00007fff5688dc20 ViewRendererHost.render(interval:updateDisplayList:) + 340
111  SwiftUI                            0x00007fff56a0a640 _UIHostingView.layoutSubviews() + 241
112  SwiftUI                            0x00007fff56a0a740 @objc _UIHostingView.layoutSubviews() + 21
113  UIKitCore                          0x00007fff24bd69a0 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2924
114  QuartzCore                         0x00007fff27a7708d -[CALayer layoutSublayers] + 258
115  QuartzCore                         0x00007fff27a7d402 CA::Layer::layout_if_needed(CA::Transaction*) + 575
116  QuartzCore                         0x00007fff27a89358 CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 65
117  QuartzCore                         0x00007fff279c8f24 CA::Context::commit_transaction(CA::Transaction*, double, double*) + 496
118  QuartzCore                         0x00007fff279ffba0 CA::Transaction::commit() + 783
119  QuartzCore                         0x00007fff27a0101c CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 79
120  CoreFoundation                     0x00007fff2038b1d1 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
121  CoreFoundation                     0x00007fff20385844 __CFRunLoopDoObservers + 547
122  CoreFoundation                     0x00007fff2038548f CFRunLoopRunSpecific + 691
123  UIFoundation                       0x00007fff23a483bd -[NSHTMLReader _loadUsingWebKit] + 1847
124  UIFoundation                       0x00007fff23a49a13 -[NSHTMLReader attributedString] + 22
125  UIFoundation                       0x00007fff239c835a _NSReadAttributedStringFromURLOrData + 9439
126  UIFoundation                       0x00007fff239c8255 -[NSAttributedString(NSAttributedStringUIFoundationAdditions) initWithData:options:documentAttributes:error:] + 144
(lldb) 
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
874
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

NSAttributedString обрабатывает цикл выполнения при анализе HTML. Вы можете увидеть это при вызове CFRUnLoopRunSpecific внутри вызова initWithData:. Это очень старая проблема с NSAttributedString. (Я думаю, что впервые столкнулся с ним в OS X 10.5, но я уверен, что он старше.)

Поскольку он обрабатывает цикл выполнения, в середине оценки строки HTML может произойти что угодно. Таймеры могут срабатывать. Отложенные селекторы могут быть вызваны. А в SwiftUI это означает, что пользовательский интерфейс может попытаться обновиться. Это беспорядок. И он генерирует условия гонки внутри, казалось бы, безопасного кода. На самом деле вам немного повезло, что Swift ловит такого рода проблемы и падает. Другие распространенные симптомы отладить еще труднее («невозможные» взаимоблокировки из-за повторного входа кода — наиболее распространенные из тех, с которыми я сталкивался).

Короткий ответ: небезопасно использовать NSAttributedString для синхронной оценки HTML. Документы не предупреждают вас об этом, и название метода не дает никакого намека на это. Но ты не можешь. Некоторые люди посоветуют вам просто убедиться, что вы оцениваете это в основном потоке, но даже это не гарантирует, что у вас не будет действительно странных ошибок повторного входа, если у вас есть что-то еще, ожидающее выполнения в цикле выполнения.

Вам нужно будет оценить эту строку другим способом. Например, см. ответ Martin R на Как декодировать объекты HTML в Swift?

В качестве быстрого примера того, как даже выполнение этого в основном потоке может привести к проблемам, рассмотрим следующий код:

func delayed() {
    print("Should be last")
}

func dothing() {
    // Run this on the next runloop
    DispatchQueue.main.async { self.delayed() }

    // These should print in order
    print("Prints first")
    print("It&#39s a party!".decoded)
}

// somewhere on the main queue. There's no background threads needed
dothing()

Это выводит:

Prints first
2020-12-20 22:16:07.976101-0500 test[84698:5693517] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x600000bb8520> F8BB1C28-BAE8-11D6-9C31-00039315CD46
Should be last
It's a party!

Если delayed мутирует какое-то состояние, то может что-то измениться из-под вас, хоть все в основном потоке.

(Странная ошибка возникает, потому что я тестировал это в didFinishLaunching, и это означает, что цикл выполнения обрабатывается до того, как приложение завершит запуск. Это именно те ошибки, которые вы получаете с этим.)

Другие вопросы по теме