WWDC Quick Look đź’“ By SwiftGGTeam
What's new in Photos

What's new in Photos

Watch original video

Highlight

WWDC25 adds a new editing node chain and scene filtering to PhotoKit, so third-party apps can reuse the system’s visual understanding directly.


Core content

The hardest part of a photo app is picking a photo. A user’s library holds thousands of images, and scrolling through them is already a chore. Asking the user to pick “a good cover shot” or “one with food in it” out of that pile only makes things worse. Developers used to run a second pass of local visual analysis after the user picked, dropped the irrelevant photos, and then sent the rest down the pipeline. The cost was a hot device, a drained battery, and analysis code to maintain.

This session offers a different fix: expose the classification results the system has already computed. When a photo enters the library, the system runs scene recognition, face clustering, and text recognition. Until now those results only fed system features like For You and Memories. PhotoKit now hands them to third-party apps. At pick time, PHPicker can show only photos that match a scene. At edit time, a new node chain describes what you want to do, and the system decides how to schedule the work. The whole idea is to split “compute” from “decide how to run.”


Details

The shape of the PHPicker API stays the same. You still bring up the picker with PHPickerViewController. The difference is that PHPickerConfiguration now takes options that tell the system to “only show photos that match this filter.” The basic call still looks like this:

import PhotosUI
import SwiftUI

struct PhotoPickerExample: View {
    @State private var selection: [PhotosPickerItem] = []

    var body: some View {
        PhotosPicker(
            selection: $selection,
            maxSelectionCount: 5,
            matching: .images
        ) {
            Label("Choose Photos", systemImage: "photo.on.rectangle")
        }
    }
}

Key points:

  • PhotosPicker is the SwiftUI wrapper around PHPicker. selection binds to a [PhotosPickerItem] array that holds the result.
  • maxSelectionCount caps the number of items. Leave it out for single selection.
  • matching: takes a PHPickerFilter and decides what shows in the picker. The common ones are .images, .videos, and .livePhotos. The new version lets you stack finer conditions on top, such as restricting to a source album or to screenshots only.

Reads and writes still go through PHPhotoLibrary. Requesting permission and registering for change notifications are two separate jobs. The new release pushes you to move change tracking onto an Observable-based API, so SwiftUI views can subscribe to library changes directly and you can drop the boilerplate of a hand-written PHPhotoLibraryChangeObserver.

import Photos

func requestLibraryAccess() async -> PHAuthorizationStatus {
    await PHPhotoLibrary.requestAuthorization(for: .readWrite)
}

Key points:

  • requestAuthorization(for:) returns the status as an async call, no nested callback needed.
  • Pass .readWrite when you need both reads and writes. For read-only flows, pass .addOnly or stick with .readWrite — pick the smaller scope you can get away with.
  • The return value is a PHAuthorizationStatus enum. Handle three cases: .authorized, .limited, and .denied. In .limited mode the user has granted access to a subset of photos. The app still works but sees fewer assets.

The edit flow still uses PHAssetChangeRequest to change asset metadata and PHContentEditingOutput to write back the edited result. The new node chain sits on top of these two APIs as a description layer. Instead of a linear “crop, then color, then filter” sequence, you describe each step as an independent node. That way, changing one step in the middle doesn’t force a recompute from scratch.


Takeaways

  • Do this: replace your in-house image classifier with PhotoKit scene filtering

    • Why it pays off: the system already classified the photos on-device, so reusing the result costs nothing. Running your own model burns battery and adds code to maintain.
    • How to start: list every place in the app that needs scene filtering — “upload a food photo,” “pick a landscape for the wallpaper” — and switch those pickers to the system filter.
  • Do this: rebuild multi-step photo editing on the node chain

    • Why it pays off: users expect “undo one step in the middle” and “turn off this one filter.” The old linear output model can’t carry that.
    • How to start: pick the most complex edit path, usually crop + color + filter + watermark. Move that one to the node chain first and verify the undo flow. Migrate the rest in batches after that.
  • Do this: switch PHPhotoLibraryChangeObserver to the Observable API

    • Why it pays off: small change, low risk, but SwiftUI views start reacting to library changes for free, and the app stops doing pointless refreshes in the background.
    • How to start: grep for every PHPhotoLibraryChangeObserver in the code, wrap it in an @Observable type that the view layer can read, and replace them one by one.
  • Do this: hard-code a “minimum viable” filter on every picker

    • Why it pays off: by default the picker shows the whole library. A reasonable starting filter trims the critical path right away.
    • How to start: review the matching: argument at every PhotosPicker call site and tighten it based on what that screen is actually for.

Comments

GitHub Issues · utterances