Reading view

There are new articles available, click to refresh the page.

How to stop Safari quitting unintentionally

I don’t always hit the right keyboard shortcuts. Of those that I commonly get wrong, by far the most serious are Command-W and Command-Q in Safari. While the former just closes the frontmost window, the latter quits the whole app, and can lose the contents of online forms. Why can’t Safari show a confirmation alert before quitting, so I can cancel those unintentional quits?

No alert is going to stop you from using the wrong keyboard shortcut. All it will do is annoy you every time you want to quit Safari and press the correct keys. At worst, when you press Command-Q but intended Command-W, you’ll accidentally click on the wrong button in the alert and go ahead with quitting Safari. The error isn’t quitting the app, it’s pressing the wrong keys, and you’ll continue to do that unless you train yourself out of it, or change your practice to make it more robust.

Historically, keyboard shortcuts for quitting apps and closing windows have long been set as Command-Q and Command-W, as Q stands for Quit and W for Window. It’s unfortunate that the two keys are immediately adjacent, so making it easy to press the wrong one, particularly if you hunt and peck for keys rather than being a touch typist.

If you’re having this problem in Safari, then you’re most likely doing the same in other apps, although its impact there may not be as apparent. That’s because most other apps track changes made in open documents for this purpose, but that’s not something that Safari can do with web pages, as entering your own text within them is tracked by the remote web server, not the browser. This should be mitigated by any website that you’re entering text into: the server should either record those entries as you make them, or at least give you the option of saving them. That’s a basic expectation of accessible website design.

Solution

You may find it helpful to enable Ask to keep changes when closing documents in Desktop & Dock settings. Coupled with disabling the control below, to Close windows when quitting an application, that should bring more protective app behaviour.

It might seem tempting to try changing the shortcut for Quit, but as far as I can see, you can’t do that for all apps. Changing it for just one or a few introduces a major inconsistency, and only increases the risk of error.

The best way you’re going to address this is to remove its root cause, by not pressing Command-Q when you don’t want to quit Safari, and that requires you to close windows a different way. Readily available in macOS is the choice of:

  • closing windows by clicking on their red Close button at the top left;
  • using the Close command in the File menu;
  • assigning a different key combination, and using that to close windows in all apps.

Although you don’t appear able to change the shortcut for Quit in all apps, you can for Close. Open Keyboard settings, click on Keyboard Shortcuts…, then on App Shortcuts at the left. Click on the + tool to add a new shortcut, and set that for All Applications, with a Menu title of Close, and a shortcut of something like Command-Shift-M. You may find Apple’s list of keyboard shortcuts helpful to ensure there are no conflicts. Whichever you choose, you should apply it consistently across all your apps. This keeps it standard and simple and makes it automatic.

Of those three options, my preference is invariably for the first, using the window’s Close button. That’s because it works independently of whichever window is at the front and ‘in focus’. With a little care checking which window you apply it to, it should be completely free of error. The disadvantage of both the Close menu command and its shortcut Command-W is that you might have a different window in focus, so sometimes you will end up closing the wrong one by mistake.

Training

Once you have chosen which to use, train yourself rigorously to use that, and that alone. When working with single-window apps you have the choice of using either, and you should consciously go through the process of thinking that through before deciding which control to use, to remind yourself of what you are doing and why.

The goal is to make closing windows and quitting apps, including Safari, thoroughly reliable processes, so you never make a mistake. That makes any warning alert superfluous, and you’ll then agree that it would only serve to irritate. That’s why better interface guidelines caution against displaying an alert unless there’s a compelling reason to do so, and not routinely whenever quitting an app.

Last Week on My Mac: Plan ahead with this summer’s mallyshag

Summer is an unpredictable time of year. With the Atlantic hurricane season already upon us, we could see searing heat or devastating storms. So it is with the announcements made at WWDC earlier this month: do we have time to try out some of the new features coming in three months, or must we get on with wrangling deprecations and changes looming in macOS Tahoe?

A glance through Apple’s beta release notes might suggest it should prove innocuous, and the great majority of code that’s already happy in Sequoia should have no problems in Tahoe, and so far that’s my experience. That should leave us plenty of time to adjust our app icons so they display properly in the Dock and elsewhere, but it’s there it gets more subtly complicated.

Fix app icons

I don’t think I can over-stress the importance of using Icon Composer for creating replacement app icons. If you don’t, then Tahoe seems determined to deface many traditional icons so they become almost illegible and unusable. The only exemptions are those already conforming to the fixed outline of a square with rounded corners. Any irregularity such as putting a pixel outside that, and they’re relegated to the sin bin.

Here are two icons for the same app viewed in Tahoe. The left one uses a traditional AppIcon.icns icon image, while that on the right is the same circular PNG that has been applied using Icon Composer and added as a .icon file. So far my attempts to get this to work using Xcode 16.4 have been unsuccessful, and the only solution has been to use a beta-release of Xcode 26.

Overhaul controls

That brings with it another problem, as it automatically converts AppKit and SwiftUI layouts so they use Tahoe’s new interface style, and that can generate further work. If you look closely at Apple’s demos of Tahoe at WWDC, you may notice that its controls have changed in size and shape. Not only do most have more rounded corners, but they also have different dimensions.

Interface conversion for apps that use AppKit or SwiftUI is clever, as it preserves the original for use in previous versions of macOS, and only adopts the new style when in Tahoe. Build your app with its smart new Tahoe-compatible icon and run it in Sequoia, and it looks just the same as it did.

This demo, Mallyshag, looks the same in Sequoia, but has become a mess in Tahoe because of those changed control dimensions.

Those three buttons are significantly wider, so now overlap one another and are wider than the text box below. They need a careful overhaul before they’re ready for Tahoe. Conversion can also have unexpected side-effects: for example, I’ve had some selectable text fields changed to be editable as well. You can see an example that I missed in the left view in XProCheck’s window. I now check carefully through every detail in windows that have been migrated by Xcode to support Tahoe.

This doesn’t just apply to AppKit windows in Interface Builder. Although SwiftUI dynamically positions controls, I’ve found it necessary to increase the minimum width of some views to ensure they remain fully usable.

Aside from any code changes needed, migrating an app to Tahoe thus requires:

  • creation of a new app icon using Icon Composer;
  • adding the .icon file to the Xcode project and setting it as the app icon;
  • careful checking and rectification of all windows and their contents.

NSLog

There’s one last thing that may have escaped your attention in Apple’s release notes: NSLog. When Apple introduced the Unified log in macOS Sierra, it preserved the longstanding use of NSLog as a means of making entries with a minimum of fuss. More formal methods are more cumbersome, although they’re also more powerful, so NSLog still remains popular with developers, at least until Tahoe’s change.

A long way down the release notes, and oddly announced under the subheading of New Features, Apple states that NSLog will no longer record anything of use in its entries in the Unified log, although they’ll still be reported in full in Xcode and to stdout. One of the other purposes of my test app Mallyshag was to verify just what is now recorded by NSLog.

This is the entry obtained using LogUI when running either version of the app in macOS 15.5:

And this is the extent of entries seen in macOS 26:

So what in earlier macOS might have been a useful
Error number 1467296 in Mallyshag
is redacted to the contentless stub <private>.

If you still use NSLog, you’ll almost certainly want to move on to a better alternative, again being careful to avoid ending up with its contents redacted.

Outcomes

Come the release of macOS 26 Tahoe, there’ll be three groups of apps:

  • those that haven’t been ported at all, whose icons will be almost unrecognisable;
  • those whose icons display correctly, but with flaws in interface controls;
  • those that work as expected, with conformant icons and controls.

Some will also write dysfunctional messages in the log, because they’re still using NSLog, although few users are likely to notice that.

That doesn’t take into account those apps relying on alternatives to AppKit and SwiftUI for their interface, as those have a great deal of ground to cover in just a few months if they’re going to be ready in time for Tahoe’s release.

That’s why I’ve started unusually early in getting my apps ready for the autumn/fall. I’m sure that summer still has some surprises in store.

Mallyshag?

This is a local Isle of Wight name for a caterpillar, usually a large and hairy one. It just seemed appropriate.

merianlappet
Maria Sibylla Merian (1647–1717), Metamorphosis of the Lappet (after 1679), watercolour, 19.3 x 15.9 cm, Städelsches Kunstinstitut und Städtische Galerie, Frankfurt am Main, Germany. Wikimedia Commons.

Last Week on My Mac: Fidelity in design

Quick Look is one of those unsung heroes that have transformed our Macs and workflows. What used to require a specialist app can now be accomplished in the Finder using a combination of Quick Look and Gallery view to browse collections of images.

This started back in Classic Mac OS, when apps created thumbnail images and attached them as ICN# resources to the original files for display in the Finder. It wasn’t until Mac OS X 10.5 Leopard in 2007 that Apple added Quick Look to perform this automatically using cached thumbnails and previews. Since then our Macs have worked hard to ensure that, wherever we want them, we can see faithful miniatures, at least until macOS 11 Big Sur.

Although the redesign brought by Big Sur in 2020 was generally well received, one feature I complained about at the time was its effect on Quick Look thumbnails and previews, in rounding their corners to conform to its design style. But style triumphed over fidelity, and for the last five years Quick Look has been forced to tell lies in every image thumbnail and preview.

By now you’ll have guessed I’m no fan of Apple’s new-found obsession with rounding every right angle in sight. I have yet to see any objective evidence that this has any purpose beyond aesthetics. If you’ve seen screenshots of the first developer beta-release of macOS 26 Tahoe, then you’ll surely have noticed that, rather than restoring fidelity to Quick Look, this fiction has grown and only become more prominent. I demonstrate this in a series of four screenshots showing the same image that have been rescaled to similar display sizes.

This first is taken from a small, almost thumbnail-size, image in the Finder’s Gallery view. As this has been scaled up, it’s pixellated. I draw your attention to the upper corners, where trees have been cropped at what once would have been right angles.

Seen here is the same image in a larger Gallery view. The extent of the cropping at the upper corners is now apparent, where this contains details that were removed from the smaller image above.

When opened in Preview, the upper corners are no longer rounded, and show the full extent of the image, but the lower corners remain cropped by enforced rounding, apparently to make them ‘concentric’, as is the vogue.

To see the whole image rendered faithfully, I had to resort to a third-party app, here GraphicConverter 12, which has the honesty to display all four corners without cropping.

One of the cornerstones of the Mac from its earliest days is expressed in the principle of WYSIWYG, what you see is what you get. It enabled the ‘desktop publishing revolution’ that convinced so many to pay the premium for Classic Macs, and ever since has guided the development of Mac OS. Without it there would be no purpose to Quick Look in its efforts to render images faithfully.

That doesn’t merit mention in the principles expounded in Apple’s latest revised Human Interface Guidelines. Three are given there, hierarchy, harmony and consistency, but not fidelity. Rounding corners of rectangles is included there under the principle of harmony: “Align with the concentric design of the hardware and software to create harmony between interface elements, system experiences, and devices.”

I can live with concentricity in windows and controls, even with app icons forcibly constrained within rounded rectangles. What I simply can’t accept is a Macintosh, of all computers, cropping every thumbnail and preview for the sake of aesthetics, however harmonious that might seem. For without fidelity, the Mac fails.

Why I like SwiftUI List Views

Presenting complex verbal information in an accessible way remains one of the great challenges in interface design. This article explains how SwiftUI List Views offer solutions that are superior to those provided in AppKit, and why I have chosen to use them in several of my recent apps, such as LogUI and AppexIndexer.

Each of the apps I discuss here has a common problem: it has to display a series of text records consisting of fields whose contents can be completely empty or expand into long paragraphs. Thus the condensed length of each row, representing a single record, can be as short as 30 characters, or as long as hundreds, some with embedded line-breaks. Fields contain contrasting data, such as datestamps, flowing text and UUIDs. The user needs to scan rows rapidly, following patterns in fields and their contents, and to read each carefully.

There are some ground rules, notably:

  • rows must remain visually separate,
  • the order of fields in each row must be the same,
  • each field must be displayed in full and not truncated,
  • fields must be visually distinct across each row,
  • field width must be adjusted automatically to avoid horizontal scrolling.

There are centuries of experience in print design of tables, to which computers add dynamic resizing of columns and ready use of colour.

tuneperf2

In some circumstances, AppKit’s Table View works well, here in Activity Monitor. However, adjustable column widths can’t overcome one problem shown here, where uniform column width wastes space for short process names, and truncates others.

logui00

This shows how poorly a Table View copes with log entries in Console.

ulbow1b103

My best solution using AppKit is for rows of untruncated text, with colour used to distinguish fields within them. Unfortunately, some rows inevitably overflow into multiple lines, and may require very wide windows to remain accessible.

This is SwiftUI’s List View in action with a log excerpt in LogUI. Although it might appear desirable to allow manual adjustment of field width, it’s more practical to provide options to change which fields are displayed, and so accommodate narrower windows. Sometimes line breaking in fields isn’t good, but I think this is a problem of content (computing terms being formed by concatenating series of words) rather than view design.

This is AppexIndexer, where I use an easily distinguished emoji to mark a significant field positioned in the middle of some rows. This aids navigation when scanning rows quickly, but doesn’t rely on the reading of the emoji.

unhidden1

Here’s another example, this time using many icons drawn from SF Symbols rather than pure text. This works well with fewer rows, but rendering many of those icons in thousands of rows may not be as efficient.

For macOS, SwiftUI continues to suffer serious omissions, and in some circumstances isn’t yet a good fit. But its List Views are a compelling reason for using SwiftUI in many native Mac apps. Further details are given in the references below, and the Appendix provides example source code for a basic implementation in SwiftUI.

Apple Developer Documentation

SwiftUI List view
SwiftUI Table view
AppKit NSTableView

Appendix: Example source code

struct ContentView: View {
    @State private var messageInfo = Logger()
    
    var body: some View {
        let _ = messageInfo.getMessages()
        if (self.messageInfo.logList.count > 0) {
            VStack {
                List(self.messageInfo.logList) { line in
                MessageRow(line: line)
                }
            }
            .frame(minWidth: 900, minHeight: 200, alignment: .center)
        } else {
            Text("No results returned from the log for your query.")
                .font(.largeTitle)
        }
    }
}

struct MessageRow: View {
    let line: LogEntry

    var body: some View {
        HStack {
            Text(line.date + "  ")
            if #available(macOS 14.0, *) {
                Text("\(line.type)")
                    .foregroundStyle(.red)
            } else {
                Text("\(line.type)")
                    .foregroundColor(.red)
            }
            if !line.activityIdentifier.isEmpty {
                Text(line.activityIdentifier)
            }
//          etc.
            Text(line.composedMessage)
            }
        }
    }

❌