Post

Replies

Boosts

Views

Activity

Reply to Printing NSTextStorage over multiple UITextView produces weird results
Thanks, that almost solves all of my issues. On macOS, and when showing the text views directly in the iOS view hierarchy, using the page break character produces the expected result. For example with the string (0..<1).map({ "\($0)" }).joined(separator: "\n") + String(UnicodeScalar(12)) + (0..<5).map({ "\($0)" }).joined(separator: "\n") the view hierarchy looks like this: But when printing them, the text views seem to overlap. I'm afraid this is now a question for a printing expert. The code below produces both the view hierarchy and the print preview. class ViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { let printController = UIPrintInteractionController.shared let printPageRenderer = PrintPageRenderer() printController.printPageRenderer = printPageRenderer printController.present(animated: true) { _, _, error in if let error = error { print(error.localizedDescription) } } var y = 0.0 for textView in printPageRenderer.createTextViews.textViews { textView.frame.origin = CGPoint(x: 0, y: y) view.addSubview(textView) y += textView.frame.height } } } class CreateTextViews: NSObject, NSLayoutManagerDelegate { let pageSize: CGSize let textStorage: NSTextStorage private let layoutManager = NSLayoutManager() private(set) var textViews = [UITextView]() override init() { pageSize = CGSize(width: 100, height: 100) textStorage = NSTextStorage(string: (0..<1).map({ "\($0)" }).joined(separator: "\n") + String(UnicodeScalar(12)) + (0..<5).map({ "\($0)" }).joined(separator: "\n"), attributes: [.font: UIFont.systemFont(ofSize: 30)]) super.init() layoutManager.delegate = self textStorage.addLayoutManager(layoutManager) if textStorage.length > 0 { let glyphRange = layoutManager.glyphRange(forCharacterRange: NSRange(location: textStorage.length - 1, length: 0), actualCharacterRange: nil) layoutManager.textContainer(forGlyphAt: glyphRange.location, effectiveRange: nil) } for textContainer in layoutManager.textContainers { let textView = UITextView(frame: CGRect(origin: .zero, size: pageSize), textContainer: textContainer) textViews.append(textView) } } func layoutManager(_ layoutManager: NSLayoutManager, didCompleteLayoutFor textContainer: NSTextContainer?, atEnd layoutFinishedFlag: Bool) { if textContainer == nil { addPage() } } private func addPage() { let textContainer = NSTextContainer(size: pageSize) layoutManager.addTextContainer(textContainer) } } class PrintPageRenderer: UIPrintPageRenderer { let createTextViews = CreateTextViews() override var numberOfPages: Int { if !Thread.isMainThread { return DispatchQueue.main.sync { [self] in numberOfPages } } printFormatters = nil var page = 0 for textView in createTextViews.textViews { let printFormatter = textView.viewPrintFormatter() printFormatter.maximumContentHeight = createTextViews.pageSize.height addPrintFormatter(printFormatter, startingAtPageAt: page) page += 1 } return page } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Apr ’25
Reply to Printing NSTextStorage over multiple UITextView produces weird results
Thanks for the suggestion, that solves the issue with the reversed pages. But each text view still contains the actual text I would expect it to contain, plus the text of all the following ones. class PrintPageRenderer: UIPrintPageRenderer, NSLayoutManagerDelegate { var pageSize: CGSize! var textStorage: NSTextStorage! private let layoutManager = NSLayoutManager() private var textViews = [UITextView]() override var numberOfPages: Int { if !Thread.isMainThread { return DispatchQueue.main.sync { [self] in numberOfPages } } printFormatters = nil layoutManager.delegate = self textStorage.addLayoutManager(layoutManager) if textStorage.length > 0 { let glyphRange = layoutManager.glyphRange(forCharacterRange: NSRange(location: textStorage.length - 1, length: 0), actualCharacterRange: nil) layoutManager.textContainer(forGlyphAt: glyphRange.location, effectiveRange: nil) } for textContainer in layoutManager.textContainers { let textView = UITextView(frame: CGRect(origin: .zero, size: pageSize), textContainer: textContainer) textViews.append(textView) } for textView in textViews { let _ = layoutManager.glyphRange(for: textView.textContainer) } var page = 0 for textView in textViews { let printFormatter = textView.viewPrintFormatter() addPrintFormatter(printFormatter, startingAtPageAt: page) page += printFormatter.pageCount } return page } func layoutManager(_ layoutManager: NSLayoutManager, didCompleteLayoutFor textContainer: NSTextContainer?, atEnd layoutFinishedFlag: Bool) { if textContainer == nil { addPage() } } private func addPage() { let textContainer = NSTextContainer(size: pageSize) layoutManager.addTextContainer(textContainer) } }
Topic: UI Frameworks SubTopic: UIKit Tags:
Apr ’25
Reply to Force NSDocument save panel to select most specific type in format popup button
For instance take the following code: class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { DispatchQueue.main.async { let document = try! NSDocumentController.shared.makeUntitledDocument(ofType: "net.daringfireball.markdown") print(document.fileType!, UTType(document.fileType!)!) NSDocumentController.shared.addDocument(document) document.makeWindowControllers() document.windowControllers[0].window!.title = "Markdown" document.showWindows() } } } And Info.plist: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>UTImportedTypeDeclarations</key> <array> <dict> <key>UTTypeConformsTo</key> <array> <string>public.plain-text</string> </array> <key>UTTypeDescription</key> <string>Markdown</string> <key>UTTypeIcons</key> <dict/> <key>UTTypeIdentifier</key> <string>net.daringfireball.markdown</string> <key>UTTypeTagSpecification</key> <dict> <key>public.filename-extension</key> <array> <string>md</string> <string>mdown</string> <string>markdown</string> <string>text</string> </array> <key>public.mime-type</key> <array> <string>text/markdown</string> <string>text/x-markdown</string> <string>text/x-web-markdown</string> </array> </dict> </dict> </array> <key>CFBundleDocumentTypes</key> <array> <dict> <key>CFBundleTypeName</key> <string>Plain Text</string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>LSHandlerRank</key> <string>Default</string> <key>LSItemContentTypes</key> <array> <string>public.plain-text</string> </array> <key>NSDocumentClass</key> <string>$(PRODUCT_MODULE_NAME).Document</string> <key>NSUbiquitousDocumentUserActivityType</key> <string>org.desairem.uFocus.OpenDocument</string> </dict> <dict> <key>CFBundleTypeName</key> <string>Markdown</string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>LSHandlerRank</key> <string>Default</string> <key>LSItemContentTypes</key> <array> <string>net.daringfireball.markdown</string> </array> <key>NSDocumentClass</key> <string>$(PRODUCT_MODULE_NAME).Document</string> <key>NSUbiquitousDocumentUserActivityType</key> <string>org.desairem.uFocus.OpenDocument</string> </dict> </array> </dict> </plist> After making sure that the document with the window title Markdown is active, press Command-S to open the default save panel: Plain Text is selected instead of Markdown.
Topic: UI Frameworks SubTopic: AppKit Tags:
Apr ’25
Reply to Change NSTextView Position
I'm interested in adding a margin to a NSTextView by wrapping it in a custom view or adding sibling views, but wasn't able to get the scroll view to keep showing the entire text view. Would you mind sharing your code?
Topic: UI Frameworks SubTopic: AppKit Tags:
Apr ’25
Reply to How to debug Quick Look Preview Extension
Unfortunately this is an ongoing issue and I still don't know how to debug my app's Quick Look Preview Extension. I tried creating a default Xcode project and I can debug it by running the Extension target, selecting Finder in the Xcode dialog, then selecting a file in the Finder and pressing Spacebar. But this doesn't work for my already existing app: the preview just shows a spinning progress indicator, even when using the exact same code in PreviewViewController.swift. The only notable difference I can think of is that my app has an iCloud entitlement. Removing that entitlement and changing the bundle identifiers of the host app and the extension to those used in the sample app get rid of the endless progress indicator... but instead cause an immediate error to be shown at the top of the preview window: "Couldn’t find extension org.domain.problem.QuickLook” I would appreciate any help, as currently the only way to test the Preview Extension is to publish it on the App Store, download it, and see if it behaves as expected, and if not, try something different and repeat the cycle. I created FB17066774.
Topic: App & System Services SubTopic: General Tags:
Apr ’25
Reply to Xcode downloads client crash report with reason "index 0 beyond bounds for empty array" but the stacktraces don't contain any of my app's symbols
Thanks for the suggestions. No user has contacted me about these kinds of issues yet, so logging wouldn't help until someone does. I don't think manipulating threads would help me, since even once I knew what thread causes the crash, I would still be looking for a needle in a haystack, without any information about the kind of function call that caused the crash. My app is an AppKit app which spawns some threads here and there with DispatchQueue. The best (and only feasible) thing, in my opinion, would be for macOS to catch invalid state early and throw a meaningful exception.
Topic: App & System Services SubTopic: General Tags:
Mar ’25
Reply to NSTextView doesn't correctly redraw when deleting text and setting attribute at the same time
I'm still using TextKit1 for backwards compatibility. [quote='831004022, DTS Engineer, /thread/776762?answerId=831004022#831004022'] If the intent of using a custom textContainerInset is to move the text down 8 points, you might be able to achieve it by moving textView down. [/quote] Yes, removing the container inset solves the issue, but I need it. Do you mean moving the scrollView down? That looks ugly. If you mean the textView inside the scrollView, how would I do that?
Topic: UI Frameworks SubTopic: AppKit Tags:
Mar ’25
Reply to Xcode downloads client crash report with reason "index 0 beyond bounds for empty array" but the stacktraces don't contain any of my app's symbols
It's entirely possible for bugs in your app to cause crashes that don't contain any of your code Ok, but if I don't see any of my code in the stack trace, it can be quite difficult (if not infeasible) to find out what caused the crash. Complex crashes (like this one) happen because your code did one or more things which created the circumstances which lead to the final failure Since I don't have the means of understanding what the final failure was, I would expect that your internal code that caused the final failure would throw some meaningful error that would allow me to understand the issue, or that an error is thrown as soon as your internal code detects that the "circumstances" or preconditions are invalid. Changing your apps implementation so that it includes clear indications of it's actual activity in the crash log. You mean also in case that the user contacts me, right? Otherwise I wouldn't know how to make this visible in the crash report. Making sure you've got a system in place where end users can contact you asking for help How could I make sure of that, or how could I detect that a crash has happened or is about to happen if I have no idea what code causes it?
Topic: App & System Services SubTopic: General Tags:
Mar ’25