In iOS 15, Apple took a step in the direction of user privacy by introducing small toast notifications every time an app accessed a users clipboard. You would all be familiar with them, they looked like this:

In iOS 16, Apple took it one further by removing the ability for apps to read the clipboard at will, instead throwing up a permission dialog every time an app attempted to read from UIPasteboard
.

Introducing UIPasteControl
Apple’s answer to this was a new UIKit control called UIPasteControl
, it works simply enough, you assign it a configuration and a target, and it’ll paste into your target when the button is tapped, all without user confirmation. That’s all well and good, but what if you read from the clipboard in a UIMenu?

Given that UIPasteControl
is a component from UIKit
, we can’t use it in UIMenu
Those identifiers we ignored
Apple’s documentation states that when instantiating a UIAction
, we can pass nil
to the identifier
argument for the method to create a unique identifier for us.
Apple Documentation
identifier
The unique identifier for the action. Specifynil
to let this method create a unique identifier for you.
And so for the most part, we ignore that identifier field. But it’s actually very useful! While you’ll need to give-up come control (like using your own SFSymbol or using a custom tile), we can pass a static variable from UIAction.Identifier
to signal to iOS what we want our action to do.
Paste Identifiers
When it comes to paste controls, Apple defines 4 types:
paste
pasteAndGo
pasteAndMatchStyle
pasteAndSearch
By using one of these identifiers for your UIAction
, iOS will let you access the pasteboard without additional user consent, as this system action is considered consensual.
Example
let menu = UIMenu(children: [
UIAction(identifier: UIAction.Identifier.paste, handler: { _ in
print(UIPasteboard.general.url) //Despite accessing the UIPasteboard here, no additional warning is given.
})
])
I’m using this in Pestle in iOS 16 and it works great 🙂
Remember, you can still query the UIPasteboard without reading the contents of it, combining a query with the above code ensures Paste is never shown to the user unless a relevant item is already on the clipboard.