Closed
Description
I've been looking at leveraging RichTextEdit, however, when ever I add the RichTextKeyboardToolbar to my view, it crashes if I try either of the two presented buttons. The crash when running on an actual device is
UITextView 0x10e895800 is switching to TextKit 1 compatibility mode because its layoutManager was accessed. Break on void _UITextViewEnablingCompatibilityMode(UITextView *__strong, BOOL) to debug.
App is being debugged, do not track this hang
Hang detected: 1.49s (debugger attached, not reporting)
App is being debugged, do not track this hang
Hang detected: 1.21s (debugger attached, not reporting)
*** Assertion failure in void BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW(Class _Nonnull __unsafe_unretained, UIView * _Nonnull __strong)(), UITargetedPreview.m:70
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This UITargetedPreview initializer requires that the view is in a window, but it is not. Either fix that, or use the other initializer that takes a target with an explicit container. (view: <_TtC7SwiftUIP33_64A26C7A8406856A733B1A7B593971F725UIKitIconPreferringButton: 0x10540ed00> → <_TtGC7SwiftUI16PlatformViewHostGVS_P10$190cd383832PlatformViewRepresentableAdaptorGVS_P10$190c72a3418UIKitButtonAdaptorVS_P10$190c72ba019PlatformItemContent___: 0x10f625680>)'
*** First throw call stack:
(0x18b4812ec 0x188905a7c 0x18a77e040 0x18e857160 0x18e8571d4 0x18f27a4a4 0x18ed7a4f8 0x18ed7769c 0x18f27a0b8 0x18f27d12c 0x18f27d1cc 0x18f27d014 0x18f279ff0 0x18e7e2ab8 0x18e6c28cc 0x18e68b7c4 0x18df8c3a8 0x18e6b3d40 0x18e6b4000 0x18deb855c 0x18deb855c 0x18deb855c 0x18deb855c 0x18dcb3bdc 0x18dcb1e44 0x18dd2802c 0x18deb8c34 0x18deb76f0 0x18deb6658 0x18de7b7c4 0x18ddfa0b8 0x18dd18c10 0x18dd1604c 0x18dd17b64 0x18dd167dc 0x18b3d9ce4 0x18b3d9c78 0x18b3d89fc 0x18b3d7c3c 0x18b3fc700 0x1d7f3d190 0x18e01a240 0x18e018470 0x18fc74f3c 0x18fc74e6c 0x18fc74d50 0x1016969c4 0x101696ac4 0x1b1dffad8)
libc++abi: terminating due to uncaught exception of type NSException
And when I run it in the simulator I get:
*** First throw call stack:
(
0 CoreFoundation 0x00000001804c88c0 __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00000001800937cc objc_exception_throw + 72
2 Foundation 0x0000000180e6999c -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
3 UIKitCore 0x00000001855323ec BUG_IN_CLIENT_OF_TARGETED_PREVIEW__VIEW_IS_NOT_IN_A_WINDOW + 140
4 UIKitCore 0x000000018553244c -[UITargetedPreview initWithView:] + 64
5 UIKitCore 0x00000001861d17fc -[UIContextMenuInteraction clickPresentationInteraction:previewForHighlightingAtLocation:] + 124
6 UIKitCore 0x0000000185b6ba54 -[_UIClickPresentationInteraction _prepareInteractionEffect] + 136
7 UIKitCore 0x0000000185b68498 -[_UIClickPresentationInteraction _performPreviewPresentation] + 36
8 UIKitCore 0x00000001861d1410 __53-[UIContextMenuInteraction _presentMenuAtLocation3D:]_block_invoke + 40
9 UIKitCore 0x00000001861d4288 __70-[UIContextMenuInteraction _interactionShouldBeginAtPoint:completion:]_block_invoke + 208
10 UIKitCore 0x00000001861d42fc __70-[UIContextMenuInteraction _interactionShouldBeginAtPoint:completion:]_block_invoke_2 + 92
11 UIKitCore 0x00000001861d4174 -[UIContextMenuInteraction _interactionShouldBeginAtPoint:completion:] + 332
12 UIKitCore 0x00000001861d134c -[UIContextMenuInteraction _presentMenuAtLocation3D:] + 416
13 UIKitCore 0x00000001854a1168 -[UIControl performPrimaryAction] + 144
14 UIKitCore 0x00000001852fecbc -[UICollectionViewCell _performCustomSelectionAction] + 32
15 UIKitCore 0x00000001852977e0 -[UICollectionViewListCell _performCustomSelectionAction] + 120
16 UIKitCore 0x00000001852b9270 -[UICollectionView _selectItemAtIndexPath:animated:scrollPosition:notifyDelegate:deselectPrevious:performPrimaryAction:performCustomSelectionAction:] + 112
17 UIKitCore 0x00000001852e98f0 -[UICollectionView _userSelectItemAtIndexPath:animatedSelection:] + 240
18 UIKitCore 0x00000001852e9b84 -[UICollectionView touchesEnded:withEvent:] + 444
19 UIKitCore 0x0000000185bf9a98 forwardTouchMethod + 352
20 UIKitCore 0x0000000185bf9a98 forwardTouchMethod + 352
21 UIKitCore 0x0000000185bf9a98 forwardTouchMethod + 352
22 UIKitCore 0x0000000185bf9a98 forwardTouchMethod + 352
23 UIKitCore 0x0000000185c07e24 -[UIWindow _sendTouchesForEvent:] + 976
24 UIKitCore 0x0000000185c0922c -[UIWindow sendEvent:] + 2820
25 UIKitCore 0x0000000185be8bfc -[UIApplication sendEvent:] + 376
26 UIKit 0x00000001ccc1a870 -[UIApplicationAccessibility sendEvent:] + 100
27 UIKitCore 0x0000000185c731bc __dispatchPreprocessedEventFromEventQueue + 1160
28 UIKitCore 0x0000000185c75e60 __processEventQueue + 4800
29 UIKitCore 0x0000000185c6e474 updateCycleEntry + 156
30 UIKitCore 0x0000000185133f04 _UIUpdateSequenceRun + 76
31 UIKitCore 0x0000000185afd9b8 schedulerStepScheduledMainSection + 204
32 UIKitCore 0x0000000185afcdd4 runloopSourceCallback + 80
33 CoreFoundation 0x00000001804284b8 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
34 CoreFoundation 0x0000000180428400 __CFRunLoopDoSource0 + 168
35 CoreFoundation 0x0000000180427b88 __CFRunLoopDoSources0 + 220
36 CoreFoundation 0x0000000180422584 __CFRunLoopRun + 780
37 CoreFoundation 0x0000000180421e3c CFRunLoopRunSpecific + 536
38 GraphicsServices 0x0000000190f62d00 GSEventRunModal + 164
39 UIKitCore 0x0000000185bcec98 -[UIApplication _run] + 796
40 UIKitCore 0x0000000185bd3064 UIApplicationMain + 124
41 SwiftUI 0x00000001d3953aa8 $s7SwiftUI17KitRendererCommon33_ACC2C5639A7D76F611E170E831FCA491LLys5NeverOyXlXpFAESpySpys4Int8VGSgGXEfU_ + 164
42 SwiftUI 0x00000001d39537d0 $s7SwiftUI6runAppys5NeverOxAA0D0RzlF + 84
43 SwiftUI 0x00000001d36e09e0 $s7SwiftUI3AppPAAE4mainyyFZ + 148
44 LetterTracker.debug.dylib 0x000000010327ef38 $s13LetterTracker0aB3AppV5$mainyyFZ + 40
45 LetterTracker.debug.dylib 0x000000010327f038 __debug_main_executable_dylib_entry_point + 12
46 dyld 0x00000001021e13d8 start_sim + 20
47 ??? 0x00000001022aeb4c 0x0 + 4331334476
)
libc++abi: terminating due to uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'This UITargetedPreview initializer requires that the view is in a window, but it is not. Either fix that, or use the other initializer that takes a target with an explicit container. (view: <_TtC7SwiftUIP33_64A26C7A8406856A733B1A7B593971F725UIKitIconPreferringButton: 0x14b5167a0> → <_TtGC7SwiftUI16PlatformViewHostGVS_P10$1d4161dcc32PlatformViewRepresentableAdaptorGVS_P10$1d40ff9d418UIKitButtonAdaptorVS_P10$1d40ffb4019PlatformItemContent___: 0x14b518050>)'
terminating due to uncaught exception of type NSException
CoreSimulator 1010.10 - Device: iPhone 16 Pro (048BC4BE-4BFE-4773-8B98-8D3577245BF1) - Runtime: iOS 18.4 (22E238) - DeviceType: iPhone 16 Pro
The view code is as follows:
/// Section containing the rich text editor for the letter body.
private var noteSection: some View {
Section("Letter Body") {
VStack {
#if os(macOS)
RichTextFormat.Toolbar(context: context)
#endif
RichTextEditor(text: .constant(NSAttributedString()), context: context)
.frame(minHeight: 200)
.font(.system(.body, design: .serif))
.lineSpacing(5)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.gray.opacity(0.2), lineWidth: 1)
)
.task {
if let attributedString = letter.noteAttributedString {
context.setAttributedString(to: attributedString)
}
}
#if os(iOS)
RichTextKeyboardToolbar(
context: context,
leadingButtons: { $0 },
trailingButtons: { $0 },
formatSheet: { $0 }
)
#endif
}
.richTextFormatSheetConfig(.init(colorPickers: colorPickers))
.richTextFormatSidebarConfig(
.init(
colorPickers: colorPickers,
fontPicker: isMac
)
)
.richTextFormatToolbarConfig(.init(colorPickers: []))
}
}
The above is called in the main view body:
@Bindable var letter: Letter
/// Environment dismiss action for closing the editor.
@Environment(\.dismiss) private var dismiss
/// Task for handling letter indexing in Spotlight.
@State private var indexingTask: Task<Void, Error>?
/// Rich text editing context for the letter content.
@StateObject private var context = RichTextContext()
/// Store manager for handling subscription status.
@StateObject private var storeManager = StoreManager.shared
/// Controls the visibility of the subscription view.
@State private var showingSubscriptionView = false
var body: some View {
Form {
recipientSection
addressSection
dateSection
contentSection
noteSection
debugSection
}
.navigationTitle(letter.subject?.isEmpty ?? true ? "New Letter" : letter.subject!)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("Save", systemImage: "checkmark.circle.fill") {
if storeManager.canSaveLetter {
saveAndDismiss()
} else {
showingSubscriptionView = true
}
}
}
}
.sheet(isPresented: $showingSubscriptionView) {
SubscriptionView()
}
}
And LetterEditor Extension:
private extension LetterEditor {
var isMac: Bool {
#if os(macOS)
true
#else
false
#endif
}
var colorPickers: [RichTextColor] {
[.foreground, .background]
}
var formatToolbarEdge: VerticalEdge {
isMac ? .top : .bottom
}
}