I fancy myself a calm and collected person. Mellow. Only very few things on this good earth rile me up enough to make me want to punch my Mac’s screen. But boy, is Apple’s App Review consistently one of them.

Prologue

I recently released ScreenFloat v2.3.8. I submitted it to the Mac App Store on July 16th, 2026, and later that day, it was reviewed and approved by App Review without any issues. I published it on July 20th.

As sometimes sadly happens though, right after the release, I noticed a crashing bug. It’s sort of obscure, but prominent enough that I would have been uneasy had I not fixed it right away. I’ll skip over the part where I panic and curse myself for missing it – that’s my own personal hell.
I fixed the bug (one line of code!) and re-submitted to Apple with an expedited review request, which was granted.

Chapter I – The Devil Is In The Details. But Where Are They!?

The update eventually entered review and was fairly soon afterwards rejected for the following reason:

This is an automated message. The review of this submission cannot proceed. See below for more information.

An automated analysis of the submission indicates the app includes placeholder or otherwise insufficient purpose strings.

Purpose strings must clearly and completely describe your use of data.

Take one of the following actions:

- If the app needs access to a protected resource that requires a purpose string, revise the purpose string to explain how the app will use the resource and provide a specific example of how the data will be used. Then resubmit for review.

- If the app does not need access to a protected resource that requires a purpose string, remove the code that’s accessing the resource and the purpose string from the binary. Then resubmit for review.

Aside from the fact that it took me a second to understand what the automated message (a first for me, by the way) meant by “purpose strings”1, I was flabbergasted.
Which purpose string does the automated process deem “insufficient” or a “placeholder”?
What does “insufficient” even mean here? Is a purpose string not clear, or too short, or not easily understandable? Is it grammatically incorrect? Is it in a localization, or the English language version?
What’s a “placeholder” considered to be in this context?
Is it objecting to my use of the protected resource, or my user-facing sentence?
Which protected resource is it objecting to in the first place?

It’s painfully ironic that they require my strings to “clearly and completely describe” my use of data, when they themselves so marvelously fail to do so.

You know what’s “insufficient”? Your freaking automated message!
They might as well have told me “Something’s preventing us from further reviewing your app. Good luck finding it, asshole!”.

Even if I only had one purpose string in my app, this would have been annoying, because that detail would help quite a bit in knowing where to look and what to change.
But I have several of them. ScreenFloat is a screen capture app, so it can record your screen, and, if you tell it to, your microphone and system audio. (And, if you enable it, your key strokes during recording, but that doesn’t need a “purpose string”.)
In addition to those, the app has a Face ID purpose string, because folders in ScreenFloat can be locked and unlocked with biometrics. It has a Pictures folder purpose string for the specific case where a v1-library-import fails for certain files, so the app can move those there.
It has an Apple Events purpose string so the app can use and interact with Shortcuts. Lastly, it has a Contacts purpose string, because ScreenFloat can Quick Look vcards encoded in QR codes, and that only works with that Contacts entitlement, otherwise no preview is shown, or worse, the app crashes. Don’t ask me why.

Long story short, ScreenFloat needs all those purpose strings, and I believe they are worded correctly. After all, they have been like this ever since they first shipped.

So I reworded two purpose strings to demonstrate goodwill, and re-submitted.

Chapter II – They’re Just Trying to Break Me Now

Another rejection. This time from an actual person. Or so I believe. It didn’t say “automated message” this time around. I’m not sure if getting escalated from an automated rejection to a human one is reason to rejoice, or to worry even harder. But I digress.

The rejection this time was much clearer, but just as infuriating.

The app uses one or more entitlements which do not appear to have matching functionality within the app.
[…]
com.apple.security.personal-information.addressbook

I see.
Apparently, App Review completely ignored – or is ignorant of – the fact that in App Store Connect2, there’s a section called “App Sandbox Information”, specifically designed for the purpose of telling App Review what entitlements your app uses, and why.
I have this. See here:

So pardon my French, but it’s freaking right there.

But I did as they did, and ignored this.
I gave them the same (paraphrased) reason via reply-to-the-rejection, and now the app is “Waiting for Review” again. What a waste of time.

Epilogue

I cannot stress enough how frustrating these inconsistent app reviews are.
If you recall from the beginning of this post, just 5 days ago, on the 16th, I submitted basically the same binary, and it went through without a hitch.
Now, a few days later, with a one-line change in the binary to fix a crash, I have two rejections for stuff that has been in the app since I can’t even remember when.

What gives, App Review?
Why waste my (and your) time with asking for info on an entitlement, when it’s already there?
Why not object to it at the very first review of that entitlement with v2.0, instead of out-of-the-blue, after goodness knows how many updates in between?
What’s with that absolutely disgusting and disrespectful automated message with no details whatsoever?
What happened between July 16th and today, five days later!?

And most importantly of all: why won’t you let me release my one-code-line-crash-fixing app update for ScreenFloat already!?

[Update]: ScreenFloat v2.3.9 was accepted by App Review on July 22nd and subsequently released.

[Update]: Apple called. And now I feel bad. I hope it was clear that I’m upset with the process, not the people behind it.



  1. A “purpose string” is the text displayed to users for requesting protected resources, like the microphone, camera, etc.
    There should be a different term for this than “purpose strings”. How about “Usage Description string”, since that’s how they’re defined in code, like “NSMicrophoneUsageDescription”? That would make it way more recognizable to developers. ↩︎
  2. The place where developers submit their apps to App Review. ↩︎
Read more

ScreenFloat for Mac v2.3.8 is now available, and brings a handful of new features, two handfuls of improvements, and three handfuls of bug fixes.

“The most used tool on my Mac”

wendylou @ Mac App Store

What is ScreenFloat?

ScreenFloat is your Mac’s Screen Capture Power Tool.
Capture screenshots and recordings that float above other windows, allowing you to reference anything on your screen, anywhere. It’s like Picture-in-Picture, only for screen captures.
It keeps your Desktop clutter-free, as every capture you make is stored in its Shots Browser, where you can manage, organize and find your shots. They’re also synced across your Macs over iCloud.
Easily copy the non-copyable, as ScreenFloat recognizes text, barcode and faces in your shots, which also allows you to effortlessly redact sensitive parts of your screenshots.
Add non-destructive annotations, redactions and markup, crop, “fold“, resize, or de-retinize your shots. Quickly pick colors.
Mute, trim and cut your recordings with the aid of “edit markers” you can place while recording. Export them as GIFs.
Create shareable and embeddable links for your captures using iCloud, ImageKit.io or Cloudinary.com.
And so much more.

A screenshot is just a screenshot. Until you use ScreenFloat.

Tip: Check out the Get to Know ScreenFloat 2 Blog Post series for a deep-dive into its functionality and what it can do for you.

“A brilliant app”

Prof. Brian Whalley @ Mac App Store

What’s New in ScreenFloat v2.3.8

Remove captured windows’ shadows after capture, just for exports, or permanently
  • If you like to capture windows with shadows, but need them without from time to time, you can now easily remove them; on-the-fly for export or dragging out, or permanently if you changed your mind. Child window’s shadows are preserved.
  • A new setting to automatically copy new shots to your clipboard
  • Widgets have been improved
    • A “Recapture” Control Widget has been introduced (macOS 26)
      • The Capture widget now also has this functionality
    • You can now choose what should happen when a shot is clicked in a widget: Float, Copy, or Reveal in Shots Browser
  • Overhauled ScreenFloat’s menu bar icon menu
  • Improved the GIF export of videos
  • Recording videos has been improved with better color fidelity and new click highlights
    • Cutting recordings is now more compatible and reliable
  • And much more, like additive, selective copying of detected data : )

👉 For the full release notes, please click here 👈

“Brilliant. Useful. Amazing.”

dan38882 @ Mac App Store

Links and Availability

ScreenFloat is a one-time purchase on the Mac App Store or my website for currently USD 17.99 / EUR 19,99 / GBP 17.99.
It is also part of Setapp.
There is no difference in functionality between the different versions.
As with all previous updates, v2.3.8 is completely free for existing customers.
A free, 28-day trial is available for download.
ScreenFloat requires macOS 12.3 Monterey (macOS 26 Tahoe recommended for full functionality)
A (free) iCloud account is required if you want to sync your ScreenFloat library across your Macs.
ScreenFloat is currently localized in English, German, Chinese (Simplified), and Dutch.

🔗 ScreenFloat Website + Free Trial + Direct Purchase
🖥️ ScreenFloat on the Mac App Store
➡️ ScreenFloat on Setapp (offers a 7-day trial for all 200+ apps, including my Mac apps Yoink and Transloader)
🤩 Eternal Storms Software Productivity Bundle on the Mac App Store (includes ScreenFloat, Yoink for Mac, Transloader and DeskMat at ~20% off)

📖 Get to Know ScreenFloat 2 Blog Post Series | User Guide
💡 ScreenFloat 2 Usage Tips

💌 Contact & Connect

A note on in-app purchases in the Mac App Store version: These are completely voluntary tips you can give me to support me and the development of my apps beyond the one-time purchase price. No additional functionality can be unlocked by giving tips. Your one-time purchase gives you to the complete functionality of ScreenFloat.

[Update July 22nd, 2026] : v2.3.9 is now available, fixing a potential crash when exporting shots, introduced in v2.3.8.

“An app that I honestly don’t know how I lived without it”

Chariklia M. @ Setapp

I hope you enjoy ScreenFloat (and my other apps) : )

“One of my most used Apps!”

paradox2222 @ Mac App Store
Read more

DeskMat for Mac v1.3.1 – a utility that quickly covers your Desktop or individual files for more privacy during screen sharing, cleaner streams, and distraction-free work – fixes a bunch of bugs and makes sure it runs well on macOS 27 “Golden Gate”.

“Exactly what I needed”

Captain Muso @ Mac App Store

What is DeskMat?

DeskMat helps you:

  • retain your privacy when sharing your screen
  • have cleaner streams
  • work distraction-free

by providing a simple cover for your Desktop.
With the click of a button, all your files and folders on your Desktop disappear, and re-appear just as easily when you need them. Alternatively, select specific files or folders, or file types, that you want to hide or keep showing.
Tie the app to your Focus modes or specific apps coming to the foreground, so the cover activates and deactivates automatically.
Create workflows with Shortcuts and AppleScript.
With Control Center widgets, you can toggle the cover from anywhere.

Tip: Check out the Get to Know DeskMat Blog Post for a deep-dive into its functionality.


What’s New in DeskMat v1.3.1

  • Makes sure it runs well on macOS 27 “Golden Gate”
  • Fixes a bug where the static or live wallpaper option didn’t work on some locales
  • Fixes a bug where sometimes the macOS Default Wallpaper failed to load

👉 For the full release notes, please click here 👈

“Focus mode integration is excellent”

tedsvo @ Mac App Store

Links and Availability

DeskMat is a one-time lifetime purchase on the Mac App Store or my website for currently USD 3.99 / EUR 3,99 / GBP 3.99.
There is no difference in functionality between the different versions.
As with all previous updates, v1.3.1 is completely free for existing customers.
A free, 28-day trial is available for download.
DeskMat requires macOS 13.0 Ventura or newer.
The app is currently localized in English, German, Chinese (Simplified), Dutch, French, Italian, Japanese and Spanish.

🔗 DeskMat Website + Free Trial + Direct Purchase
🖥️ DeskMat on the Mac App Store
🤩 Eternal Storms Software Productivity Bundle on the Mac App Store (includes ScreenFloat, Yoink for Mac, Transloader and DeskMat at ~20% off)

📖 Get to Know DeskMat Blog Post

💌 Contact & Connect

A note on in-app purchases in the Mac App Store and direct purchase versions: These are completely voluntary tips you can give me to support me and the development of my apps beyond the one-time purchase price. No additional functionality can be unlocked by giving tips. Your one-time purchase gives you to the complete functionality of DeskMat.

I hope you enjoy DeskMat (and my other apps) : )


Read more

In lieu of a software update today – ScreenFloat v2.3.8 is taking me a bit longer than anticipated – I thought I’d share a fun 🙃 story about SwiftUI with you.

ScreenFloat offers widgets that give you quick access to different things.
Among others, you have the Capture widget which allows you to start a screen recording, capture your screen, import from your iPhone, etc.
And there’s the Recent Captures widget displays your recent shots so you can easily float them.
Or so I thought. But I’m getting ahead of myself.

The Capture widget
The Recent Captures widget

All the actions in these widgets (when a button or a shot in a widget is clicked) are powered by SwiftUI’s Link(), which opens my app with a custom URL that contains whatever information I need to perform the action the user requested.
For clicked shots, that would be floating them (such a custom URL could look like this: esssf2://widget.at?shotID=<someid>&action=float).

Now, some of these widgets are static (the capture utility widget, for example, can not be configured in any way by the user and always shows the same capture buttons), while others are dynamic (widgets that display shots can be configured to only show images, or only video recordings, for example).

Configuring the dynamic Recent Captures widget

That’s all lovely, but recently I discovered something puzzling.
While my static widgets worked just fine – each button in the Capture widget was individually clickable and did the correct thing in my app –, clicking a shot in a widget to float it would not open my app with the custom URL I specified, but with the dynamic widget’s configuration intent instead.
No matter which shot I clicked, it always did the same, wrong, thing.
(A configuration intent is what internally makes customizing widgets possible; and to make things even more confusing, ScreenFloat’s dynamic widgets are set up internally partially through a .intentdefinition file (Apple’s older way to make widgets configurable), and partially through AppIntents (Apple’s modern approach) ).
So instead of my app receiving the correct custom URL which tells it which shot to float, it receives info on how the widget is configured – information not exactly useful in this context.

So I figured it had to do with the widget’s dynamic nature – a logical assumption, given that my app received the configuration intent instead of my URL.

First, I thought perhaps the .intentdefinition file and the AppIntents somehow confused each other, so I temporarily removed the definition file, but the results were the same. Dead end. (Which is good. Otherwise I would have only been able to offer my widgets on macOS 14 “Sonoma” and later, leaving behind two earlier releases of macOS that ScreenFloat supports).

So I set out to test my assumption that the widget’s dynamic nature was at fault.
I tried yet another dynamic widget, the Folders widget.

The Folders widget

It can be configured to show all, only smart, or only “dumb” folders, and when clicked, ideally opens the clicked folder in ScreenFloat’s Shots Browser.

With a smirk on my face, confidently clicking on a folder in that widget, absolutely certain it would not result in the folder being opened in ScreenFloat’s Shots Browser, what did my tired, shocked eyes perceive?

The freaking folder opened in the freaking Shots Browser! The Link() with my custom URL worked!

 

But why!? I couldn’t make sense of it.
What was the difference between the Link() in my Recent Captures widget, and the Link() in my Folders widget?
Readers dabbling in the arts of SwiftUI might have already noticed that the first consists of Image()s, while the latter is made of Label()s. So I swiftly swapped out the Image() for a Label() to test that this was indeed the culprit, and lo and behold, the widget now worked.
A shot was finally floated correctly!

 

At this point, I was desperate. Close to tears of rage. Ready to rage-quit. Not only Xcode, but also my app’s development. My profession. Coding in general. I was done.
Perhaps Image()s in Link()s are just bugged and there’s nothing I can do about it?
The thing is, I knew it worked at some point, so I fired up my virtual machines in UTM and went back to see when it started to break.
macOS 12? Fine.
macOS 13? Fine.
macOS 14? Fine.
macOS 15? Bingo.

Something on macOS 15 and later broke my widget.

So the first thing I did was to remove all modifiers from my Image() and try again. If it still didn’t work then, I’d have to find a different way to make it work. Maybe hack my own Image() implementation together. Fun times ahead.
But I got lucky for once. Removing all modifiers from the Image() did the trick.
Now all that was left to do was to go through each modifier and see which one broke things.

“How many lines of code are there?”
“About two million…”

Ready?
.widgetAccentedRenderingMode(). It was .widgetAccentedRenderingMode() that messes with Link()s.
Only specific configurations, though: While .fullColor and .accented work fine, the other two (.desaturated and .accentedDesaturated) render the Link() defunct. Guess which ones I used.

Now why is this happening? Nobody knows. I doubt Apple knows. Or cares.
Is any of this documented? LOL.
How long has this bug been around for? Since macOS 15, so for about 2 years.

Now that I knew where the bug was, out of interest I googled it, and sure enough found others with the same issue. Not something I found before, because who’d think to google for that particular setup? Nobody, that’s who.

So, there you have it. A Link() containing an Image() with .widgetAccentedRenderingMode() set to .desaturated or .accentedDesaturated will render said Link() defunct 🤷‍♂️ .
I found two ways around this: Don’t use those two properties, or don’t embed the Image() in the Link(), but have the Link() be an .overlay() modifier of the Image(), like so:

var body: some View {
    Image(...)
        .overlay {
            Link(destination: ...) {
                Rectangle()
                    .foregroundStyle(.clear)
                    .frame(...)
            }
        }
}

The downside with the .overlay{} method is that you lose any visual click-feedback, where the clicked Image() would change color on mouse down.

The Shot floats when I click it in the widget!

A radar’s been filed (FB23593239) and is now ready to gather dust in the forgotten depths that is Apple’s Feedback Assistant, never to be looked at again, until some digital archaeologist far into the future stumbles upon it and finally marks it as “works as intended”.

I’ll go now and scream into a pillow some more.

Update July 7th, 2026:
I was contacted by a very nice person on the SwiftUI team at Apple notifying me that A) I posted the wrong radar number above (fixed now, mea culpa), and B) they’re looking into it. That’s amazing, I really appreciate that. Thank you, J. and team. I humbly redact my snarky statement about Feedback Assistant.


Read more