When I launch the Quick Look Preview Extension target in Xcode, an app called Quick Look Simulator opens with an almost empty window:
Online I read that the Terminal command qlmanage allows to test Quick Look plugins (which I think were an older format for creating Quick Look extensions), but running
qlmanage -p /path/to/previewed/file -c public.text -g /path/to/QuickLookPreviewExtension.appex
(where QuickLookPreviewExtension.appex is generated by the Xcode build and is located in the DerivedData folder) gives an error
Can't get generator at QuickLookPreviewExtension.appex
How can I debug a Quick Look Preview Extension?
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
In the past, I used to export a developer-signed test version of my macOS app in Xcode, create a zip archive from the Finder, upload it to my website and share the link to the testers. The last time I did this with macOS 14 the tester was still able to download the test app and run it.
But it seems that with macOS 15 the trick to open the context menu on the downloaded app and click Open to bypass the macOS warning that the app couldn't be checked when simply double-clicking it, doesn't work anymore. Now I'm always shown an alert that macOS couldn't check the app for malware, and pushes me to move it to the bin.
In this StackOverflow topic from 10 years ago they suggested to use ditto and tar to compress and uncompress the app, but neither worked for me.
How can I share macOS apps that I signed myself with testers without physically handing them a drive containing the uncompressed app?
I was able to confirm with a customer of mine that calling copyfile with a source file that is a symbolic link on a NTFS partition always causes the error
NSPOSIXErrorDomain 12 Cannot allocate memory
They use NTFS drivers from Paragon.
They tried copying a symbolic link from NTFS to both APFS and NTFS with the same result. Is this an issue with macOS, or with the NTFS driver?
Copying regular files on the other hand always works. Copying manually from the Finder also seems to always work, both with regular files and symbolic links, so I'm wondering how the Finder does it.
Here is the sample app that they used to reproduce the issue. The first open panel allows to select the source directory and the second one the destination directory. The variable filename holds the name of the symbolic link to be copied from the source to the destination. Apparently it's not possible to select a symbolic link directly in NSOpenPanel, as it always resolves to the linked file.
@main
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
let openPanel = NSOpenPanel()
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.runModal()
let filename = "Modules"
let source = openPanel.urls[0].appendingPathComponent(filename)
openPanel.runModal()
let destination = openPanel.urls[0].appendingPathComponent(filename)
do {
let state = copyfile_state_alloc()
defer {
copyfile_state_free(state)
}
var bsize = UInt32(16_777_216)
if copyfile_state_set(state, UInt32(COPYFILE_STATE_BSIZE), &bsize) != 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
if copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CB), unsafeBitCast(copyfileCallback, to: UnsafeRawPointer.self)) != 0 || copyfile_state_set(state, UInt32(COPYFILE_STATE_STATUS_CTX), unsafeBitCast(self, to: UnsafeRawPointer.self)) != 0 || copyfile(source.path, destination.path, state, copyfile_flags_t(COPYFILE_NOFOLLOW)) != 0 {
throw NSError(domain: NSPOSIXErrorDomain, code: Int(errno))
}
} catch {
let error = error as NSError
let alert = NSAlert()
alert.messageText = "\(error.localizedDescription)\n\(error.domain) \(error.code)"
alert.runModal()
}
}
private let copyfileCallback: copyfile_callback_t = { what, stage, state, src, dst, ctx in
if what == COPYFILE_COPY_DATA {
if stage == COPYFILE_ERR {
return COPYFILE_QUIT
}
var size: off_t = 0
copyfile_state_get(state, UInt32(COPYFILE_STATE_COPIED), &size)
}
return COPYFILE_CONTINUE
}
}
On macOS, we have didMountNotification but there doesn't seem to be an equivalent for iOS. Is there a way to be notified when a volume is mounted on iOS? I would like to use it in my iOS app I'm currently porting from macOS, which starts a synchronization from the volume (which has been previously selected in a NSOpenPanel) as soon as it's mounted.
For many years I've had the following code to access the active objects of a table view in my App Store app:
class MyViewController: NSViewController: NSMenuItemValidation {
private var tableView: NSTableView!
private var objects = [MyObject]()
func numberOfRows(in tableView: NSTableView) -> Int {
return objects.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
// make view for row
}
private var activeObjects: [MyObject] {
return tableView?.activeRowIndexes.map({ objects[$0] }) ?? []
}
func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
let activeObjects = self.activeObjects
...
}
}
extension NSTableView {
var activeRowIndexes: IndexSet {
return clickedRow == -1 || selectedRowIndexes.contains(clickedRow) ? selectedRowIndexes : IndexSet(integer: clickedRow)
}
}
In one of the recent updates, I wanted to add some kind of header to the table view, so I decided to add a row at the beginning and offset the indexes by 1.
func numberOfRows(in tableView: NSTableView) -> Int {
return objects.count + 1
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if row == 0 {
// make header view
} else {
// make view for row - 1
}
}
private var activeObjects: [MyObject] {
return tableView?.activeRowIndexes.subtracting(IndexSet(integer: 0)).map({ objects[$0 - 1] }) ?? []
}
But since I added this change, Xcode regularly downloads crash reports from clients crashing during menu item validation in IndexSet.map with reason Code 5 Trace/BPT trap: 5. I assumed that I was accessing an invalid array index, so I added some debug code: the crash report would then show the invalid index beside the crashed thread's name.
private var activeObjects: [MyObject] {
return tableView?.activeRowIndexes.subtracting(IndexSet(integer: 0)).map({ i in
if !objects.indices.contains(i - 1) {
Thread.current.name = (Thread.current.name ?? "") + ". Invalid index \(i - 1) for count \(objects.count)"
preconditionFailure()
}
return objects[i - 1]
}) ?? []
}
But the crash reports for this new app version look just like the old ones and the thread name is not changed. Indeed, when recreating an invalid index access on my Mac, the crash report mentions Array._checkSubscript(_:wasNativeTypeChecked:), which does not appear in the crash reports downloaded by Xcode.
Manually symbolicating the crash report also doesn't give any more information: all lines referring to my app code are resolved to either /<compiler-generated>:0 or MyViewController.swift:0.
Apparently the problem is not an invalid array index, but something else. Does anybody have a clue what the problem could be?
(Note: the crash report mentions Sequence.compactMap because now I'm effectively calling tableView?.activeRowIndexes.compactMap, but the same crash happened before when calling IndexSet.map, which would appear in the crash report as Collection.map.)
crash2.crash
I can run my app on my MacBook Pro running macOS 10.14.6, but an App Store user reached out to report that it crashes immediately when launching it. When that user runs it from the Terminal, it prints out this:Illegal instruction: 4
My Mac app uses many NSTextViews just fine for printing a long string, but trying to do the same on iOS with many UITextViews and associated UIViewPrintFormatters just causes a crash.*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23d03ab1 _CFThrowFormattedException + 194
3 CoreFoundation 0x00007fff23b83bf9 -[__NSArrayM objectAtIndex:] + 169
4 UIKitCore 0x00007fff48029503 -[UITextViewPrintFormatter rectForPageAtIndex:] + 86
5 UIKitCore 0x00007fff4806bc79 __57-[UIPrintPageRenderer drawPrintFormatter:forPageAtIndex:]_block_invoke + 41
6 UIKitCore 0x00007fff4806bcf9 __57-[UIPrintPageRenderer drawPrintFormatter:forPageAtIndex:]_block_invoke.43 + 29
7 libdispatch.dylib 0x000000010e4f6d48 _dispatch_client_callout + 8
8 libdispatch.dylib 0x000000010e505b24 _dispatch_async_and_wait_invoke + 175
9 libdispatch.dylib 0x000000010e4f6d48 _dispatch_client_callout + 8
10 libdispatch.dylib 0x000000010e504de6 _dispatch_main_queue_callback_4CF + 1500
11 CoreFoundation 0x00007fff23bd4049 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
12 CoreFoundation 0x00007fff23bceca9 __CFRunLoopRun + 2329
13 CoreFoundation 0x00007fff23bce066 CFRunLoopRunSpecific + 438
14 GraphicsServices 0x00007fff384c0bb0 GSEventRunModal + 65
15 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
16 myApp 0x000000010e1ca61b main + 75
17 libdyld.dylib 0x00007fff5227ec25 start + 1
18 ??? 0x0000000000000001 0x0 + 1
)Here's the code:class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
let printController = UIPrintInteractionController.shared
let printPageRenderer = PrintPageRenderer()
printController.printPageRenderer = printPageRenderer
printController.present(animated: true)
}
}
class PrintPageRenderer: UIPrintPageRenderer {
let layoutManager = NSLayoutManager()
let textStorage = NSTextStorage(string: "fhdjksalhfj dskla fjf")
var textViews = [UITextView]()
override func prepare(forDrawingPages range: NSRange) {
DispatchQueue.main.sync {
for (i, textView) in textViews.enumerated() {
let printFormatter = textView.viewPrintFormatter()
addPrintFormatter(printFormatter, startingAtPageAt: i)
}
}
}
override var numberOfPages: Int {
textStorage.addLayoutManager(layoutManager)
let size = CGFloat(50)
for _ in 0..<2 {
let textContainer = NSTextContainer(size: CGSize(width: size, height: size))
layoutManager.addTextContainer(textContainer)
let textView = UITextView(frame: CGRect(x: 0, y: 0, width: size, height: size), textContainer: textContainer)
textViews.append(textView)
}
return textViews.count
}
}My goal is printing a document from an attributed string and showing a custom header and footer on each page.
I create a URL bookmark with `URL.bookmarkData(options: [], includingResourceValuesForKeys: [.localizedNameKey])` and resolve it with `NSURL(resolvingBookmarkData: bookmarkData, options: [], relativeTo: nil, bookmarkDataIsStale: nil) as URL`. This works fine within my main app, but when sharing the bookmarkData via an App Group with my Share Extension, it gives the error "The file couldn't be opened because you don't have permission to view it.". Is there any way I can do this?
I haven‘t yet found an official Apple website that lists older macOS versions. Fortunately, I have kept the installers on a separate external storage after each major upgrade, but when launching them from a macOS version newer that the installer itself, macOS shows an error that it‘s not possible to install it. What is the official way of installing older macOS versions so that I can test my App Store apps?
When a file named a.txt is not downloaded locally, the iCloud Drive folder actually only contains a placeholder named .a.txt.icloud (that is still displayed as a.txt by the Finder) with a very small file size, something like 176 bytes. How can I get the original file size, like the Finder displays?
I would like to install macOS 14 Sonoma on an external partition, but I couldn't find an installer on the developer website. It seems that it's only possible to upgrade from the System Settings, so I thought I would install Ventura first on the separate partition and then upgrade to Sonoma.
I downloaded the Ventura installer from the App Store and selected the external partition during the installation, but when the Mac reboots, it just reboots into my main macOS partition. If I shut down and hold the power button pressed to select the boot partition (I have a M1 MacBook Pro 14" 2022), then nothing happens: an indeterminate progress indicator spins for a couple seconds, the partition list remains there and I can only successfully boot into my main partition again. I also tried running the installer from another macOS Ventura and macOS Monterey partition I had installed last year, but when I select the partition on which to install the new Ventura, nothing happens and I can only quit the installer.
Is there a way to debug all these issues? How can I install macOS Sonoma on a separate partition without overwriting my main macOS Ventura install?
I keep getting crash reports in Xcode for one of my macOS apps published on the App Store. Actually it's not the main app that crashes, but the embedded Finder Sync extension. The crash reports indicate that this source code line
static var appGroupSaveDirectoryUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: identifier)!.appendingPathComponent("Library/Application Support/somedata")
crashes with error
Swift runtime failure: Unexpectedly found nil while unwrapping an Optional value + 0 (<compiler-generated>:0)
That line is a static variable defined in a class that is included in the main app as well as the Finder extension.
The documentation reads
In iOS, the value is nil when the group identifier is invalid. In macOS, a URL of the expected form is always returned, even if the app group is invalid
If the documentation says that the method call can never be nil, why am I getting this crash? Is it a bug or is the documentation wrong, or am I doing something wrong? And why does the Finder Sync extension crash and not the main app? I cannot reproduce this crash with the App Store app or within Xcode and Console shows no crash reports for the app on my Mac.
For the current app, I can get the Application Scripts directory with FileManager.url(for: .applicationScriptsDirectory, in: .userDomainMask, appropriateFor: nil, create: true), but I cannot find a similar API for application groups. Does one exist, or do I have to construct the URL manually? That would probably be ~/Library/Application Scripts/[app group id], but there doesn't seem to be a FileManager API to access ~ either, as FileManager.default.homeDirectoryForCurrentUser returns /Users/username/Library/Containers/[app id]/Data/.
With a Button I can directly copy contents to the clipboard via UIPasteboard.general.setObjects(objects), but this is iOS-specific so I was hoping that ShareLink would allow me to share items in a platform-independent way. Is it possible to show a Copy item in the ShareLink sheet?
import SwiftUI
struct ContentView: View {
let myType = MyType()
var body: some View {
ShareLink(item: myType, preview: SharePreview(myType.text))
}
}
class MyType: Transferable {
let text = "asdf"
static var transferRepresentation: some TransferRepresentation {
ProxyRepresentation { myType in
return myType.text
}
}
}
#Preview {
ContentView()
}
This crash report for one of my apps was downloaded by Xcode. Apparently the app crashed while releasing an object of type Scan.File, which is a Swift class held in an array in the Scan.Directory class. I'm not doing any manual reference counting or low-level stuff with that object.
What could cause such a crash?
crash.crash