Post

Replies

Boosts

Views

Activity

Avoiding rasterizing UITextView when exporting to PDF
I'm trying to render a UIView to PDF, while maintaining text elements as actual text and not rasterizing them. I'm using TextKit 2 backed UITextView and NSTextLayoutManager to provide the contents. However, no matter what I do, UITextView gets rasterized into a bitmap. Here's the basic code: let renderer = UIGraphicsPDFRenderer(bounds: pageRect, format: format) let data = renderer.pdfData { (context) in for page in self.pageViews { context.beginPage() let cgContext = context.cgContext page.layer.render(in: cgContext) } } A page view usually contains one UITextView, which uses somewhat advanced layout, so unfortunately I can't just toss it into a single NSAttributedString and draw into a CoreText context. There's a hack to get UILabels to render themselves as non-rasterized text, and if I understand correctly, it works by just actually drawing them on the current context. Interestingly, when providing UILabel view via NSTextAttachmentViewProvider to a text view using TextKit 2, the UILabels inside a text view won't get rasterized. In the image below, the paragraph is a bitmap, while the heading is real text. This hinted that the actual text fragments are the ones that get rasterized when drawing, not the whole view, and I was right. I can enumerate the text fragments and draw them directly on the context, which makes them remain as text rather than become a bitmap: page.textView?.textLayoutManager?.enumerateTextLayoutFragments(from: location, options: [.ensuresLayout, .estimatesSize, .ensuresExtraLineFragment], using: { fragment in let frame = fragment.layoutFragmentFrame fragment.draw(at: frame.origin, in: cgContext) return true }) This causes other issues, because layout coordinates will be all over the place and not confined to the text view itself (and even more so for my custom NSTextLayoutFragment class). I can get around this, but my text attachments won't get drawn this way either, but display a skewed placeholder icon: I can render them correctly on the context manually: if fragment.textAttachmentViewProviders.count > 0 { if let view = fragment.textAttachmentViewProviders.first?.view { view.layer.render(in: cgContext) return true } } This renders them at 0, 0 though. Edit: Changing bounds or frame for view/layer has no effect. I'm wondering if there is a way to make UITextView and NSTextLayoutManager to draw their contents this way automatically, so the fragments would remain as text in the PDF, rather than become a bitmap? It seems weird that the text view doesn't do this by default like it does on macOS, especially as it appears to be entirely possible. Or, if that's not possible, what's the correct way of drawing my text attachments when enumerating NSTextLayoutFragments?
2
0
761
Jan ’24
TextKit 1 anti-aliasing on macOS Sonoma
I've run into a very strange bug on macOS Sonoma, and I'm guessing it's caused by TextKit 1/2 compatibility issues. Whenever the caret is drawn on the last line of NSTextView, the anti-aliasing or drawing rect or something changes, causing the text in the current line fragment rect to wiggle up and down. See the example below: (Note that in this image, I'm using custom caret drawing to test that if that would solve something — it didn't.) The effect is more apparent on non-Retina displays, but still present on Retina screens as well. I'm using TextKit 1 because I'm maintaining compatibility with older systems, and can't move away just yet. The behavior can't be reproduced on any other OS than Sonoma. My NSTextView is scaled using scaleUnitSquareToSize but no matter the scale, the issue seems to be present. Text view also has custom input attributes, which includes line height, but drawing doesn't appear to be affected by that. Has anyone else encountered similar issues on Sonoma, and do you have any suggestions on how to proceed with debugging this?
2
0
746
Nov ’23
Printing WKWebView to PDF in macOS 11.0+
As WKWebView contents can finally be printed out in macOS 11+, I'm trying to replace my old WebView dependencies. However, with the HTML correctly loaded in WKWebView, creating PDF files using NSPrintJobDisposition: NSPrintSaveJob produces blank, empty documents. They have the correct page count and sizing, but remain empty. Using the same code without NSPrintSaveJob works just fine. This is how I'm printing the contents: NSPrintInfo *printInfo = NSPrintInfo.sharedPrintInfo; [printInfo.dictionary addEntriesFromDictionary:@{ NSPrintJobDisposition: NSPrintSaveJob, NSPrintJobSavingURL: url }]; NSPrintOperation *printOperation =[(WKWebView*)_webView printOperationWithPrintInfo:printInfo]; printOperation.view.frame = NSMakeRect(0,0, printInfo.paperSize.width, printInfo.paperSize.height); printOperation.showsPrintPanel = NO; printOperation.showsProgressPanel = YES; [printOperation runOperation]; Setting showsPrintPanel as true and uncommenting the dictionary produces traditional prints, and the results look completely normal. In both cases, I'm calling the runOperation only after navigation has actually finished. I'm confused about what I am doing wrong, or is printing from WKWebView still this buggy?
2
0
1.5k
Apr ’22
Document controller's recent files list cleared between versions
I have a document-based app. Whenever I'm publishing a new version on App Store, and even when setting a new build number, my app completely loses the recent files list. I'm accessing the list using recentDocumentURLs, but the recent documents are also lost from the File -> Recent files menu. This started happening when I started building my app on Monterey. When built in Big Sur, this doesn't happen. I'm guessing this is not a feature, because other apps don't seem to behave this way when downloading a new update. I'm guessing something has changed in sandboxing or somewhere else, and I'm missing it?
0
0
642
Apr ’22
Determining automatic scroll position in NSTextView
I have an NSTextView which uses syntax highlighting via textDidChange delegate method. Its contents are scaled using scaleUnitSquareToSize. Automatic scrolling works correctly when user reaches the bottom of the screen and line wraps — if this happens in the middle of the document. At the end, however, the scrolling seems to jump erratically for the first couple of characters. Causes of the issue I've tracked down the issue to a certain call order. Normally, textDidChange: is called between NSTextView keyDown: and NSClipView _scrollTo:, but not when the line gets so long it wraps. When typing will cause the line to wrap, the call stack looks like this (from bottom to top): [NSTextView adjustScroll:] [NSClipView _scrollTo:animateScroll:flashScrollerKnobs:] [NSTextView keyDown:] This is how it usually looks: [NSTextView adjustScroll:] [NSClipView _scrollTo:animateScroll:flashScrollerKnobs:] [Document textDidChange:] [NSTextView keyDown:] I have no idea how keyDown and _scrollTo determine where to scroll, but it seems that at some point, the text view scale is not taken into account, or gets calculated incorrectly. Solutions? I've tried wrapping my syntax highlighting in textStorage.beginEditing() and .endEditing(), which kind of fixes the issue, but also causes even more scrolling glitches when pressing space or deleting backwards. I also tried disabling adjustScroll in the text view while syntax highlighting has not yet taken place, but that, too, causes completely random jumps in scroll position, again when inserting a space or deleting. I'm trying to figure out how and where NSTextView determines the scroll position. There is no visible method in the call stack, but there has to be a method that checks if caret is in view and how to reposition content view's bounds, right? ...... Right? Any help or hints would be appreciated.
0
0
789
Apr ’22
Display/constraint update cycle crashes in macOS 11/12
I recently migrated to macOS Monterey to build my macOS app. After building the app in 12.3, the users have started to experience mysterious crashes related to view layout. The first one was somehow related to NSScrollView endlessly resizing itself between two width values, and I figured it could have something to do with scroll bar sizing, but found no apparent fix. Crashing on exception: The window has been marked as needing another Display Window pass, but it has already had more Display Window passes than there are views in the window. I circumvented the issue with some duct tape, but ended up with another layout exception on other users' systems: Crashing on exception: The window has been marked as needing another Update Constraints in Window pass, but it has already had more Update Constraints in Window passes than there are views in the window. It's very hard to debug this, because the bug seems to be very system-specific. However, by intense googling, I've seen that Safari and Xcode have also suffered from the exact same crash, but I've found no information on how they might have been fixed. I'm starting to suspect that there is something principal that has been changed within view layout routines macOS 11/12 that I'm completely missing. Does anyone have any experience with such issues, and how to start digging deeper?
4
0
1.9k
Mar ’22
NSDocument(NSDocumentSaving) bad access
I'm getting random crashes in a background thread in my document-based app. NSDocument(NSDocumentSaving) causes EXC_BAD_ACCESS (SIGSEGV) / KERN_INVALID_ADDRESS Thread 10 Crashed:: Dispatch queue: com.apple.root.default-qos 0 libobjc.A.dylib 0x00007fff2020581d objc_msgSend + 29 1 com.apple.AppKit 0x00007fff237b1909 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_4.860 + 245 2 libdispatch.dylib 0x00007fff201bc623 _dispatch_call_block_and_release + 12 3 libdispatch.dylib 0x00007fff201bd806 _dispatch_client_callout + 8 4 libdispatch.dylib 0x00007fff201bfe37 _dispatch_queue_override_invoke + 775 5 libdispatch.dylib 0x00007fff201cc818 _dispatch_root_queue_drain + 326 6 libdispatch.dylib 0x00007fff201ccf70 _dispatch_worker_thread2 + 92 7 libsystem_pthread.dylib 0x00007fff20364417 _pthread_wqthread + 244 8 libsystem_pthread.dylib 0x00007fff2036342f start_wqthread + 15 I'm wondering how I could start debugging the issue, and need some help with deciphering the crash log. Am I correct, that based on the error log, the NSDocument which is being saved does exist? In that case, it would be just some other variable which has disappeared somewhere, meaning either the NSURL or completionHandler? Or is the whole NSDocument a corpse at this point? The crash occurs very randomly, so it's pretty hard to reproduce reliably. EDIT: I found a GitHub issue with the exact same problem. Their research points to this being a race condition, which occurs when asynchronous autosave is in progress and an edit to NSDocument is being performed. However, if I disallow asynchronous autosaves (canAsynchronouslyWriteToURL), drafts don't seem to get saved at all. Is there anything I can do to prevent the asynchronous race condition?
1
0
696
Oct ’21
sandbox_extension_consume error
I have a sandboxed, document-based app. Things usually work as intended, but sometimes the app crashes with EXC_BAD_ACCESS, after producing multiple sandbox errors. I haven't found any information about the specific errors or on how to avoid them.  [scoped] handle 0: sandbox_extension_release error [22: Invalid argument] Appname [96446:12385639] [scoped] <0x600002e4ba20 file:///....(url here)>: internal sandbox error for <StopAccessing> Appname[96446:12386186] [scoped] Scoped bookmarks can only be created for existing files or directories Appname[96446:12386810] [default] sandbox_extension_consume returned 12 sandbox_extension_consume returned 12 sandbox_extension_consume returned 12 ... ad nauseam I'm not using any custom writing methods in my NSDocument subclass and the URL that it has accessed before stopping access, does in fact exist. The most cryptic error is sandbox_extension_consume returned 12. There is no information about it available anywhere, and until recently, it didn't cause any problems, but now it has started crashing the app, giving the aforementioned bad access. What am I doing wrong and where? What is sandbox_extension_consume and why does it return 12?
4
0
1.2k
Oct ’21
Updating via App Store while the app is running wipes out the current document
I have a document-based app that's available on the App Store. When the user updates the app while it's still open, any files that are being worked on get wiped clean (meaning the original files on the hard drive), with the string (null) written into them. The app does not force anything to be saved on closing, I'm not using autosavesInPlace and nothing should return null as file contents. There should be no reason for the App Store to cause this behavior. I've experienced similar oddities with other apps when downloading an update while the app is still running, but I really would like to find out why and where this happens. Does App Store suppose the app is using autosavesInPlace, and try to force it to save the document before relaunching, or what is going on? I've read through the docs to find any methods to catch these situations, but there seem to be none. It's also a quite hard one to debug. Is there a way to reproduce a somehow similar situation, in which the app gets updated via App Store while still running?
0
0
579
Sep ’21
Debugging JavaScriptCore heap crashes in Big Sur
I have a JavaScriptCore scripting interface in my app. After migrating to Big Sur, I'm getting constant crashes after the context has already been abandoned and all of the code evaluated. I have multiple JSContext instances, each with their own virtual machine, one created for all of the scripts separately. I'm getting both general protection faults (EXC_I386_GPFLT) and more general bad access crashes (ie. Heap Helper Thread (30): EXC_BAD_ACCESS (code=1, address=0x7ffdde3bdf0) I'm guessing that something somewhere tries to access stuff that is no longer there, even though this shouldn't happen as any execution has already ended. Is there a way to create some sort of protection against this, and how do I effectively debug these errors? Can't really step into evaluated JavaScript :-) Also, is there a way to effectively null the context and VM after execution to tell them that they are no longer needed?
0
0
769
Sep ’21