Я получаю сообщение об ошибке при декодировании html-элементов с помощью NSAttributedString
. Я использую Swift 5. Я хочу только html для строки. Мне не нужен веб-просмотр.
Текст SwiftUI
Text("It's 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)
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's 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
, и это означает, что цикл выполнения обрабатывается до того, как приложение завершит запуск. Это именно те ошибки, которые вы получаете с этим.)