Image Playground Sheets

Last updated on 24 Oct 2024.

Written by Jia Chen.

Swift Playgrounds for iPad app icon

Sample Project

Image Playground Sheets

Last updated on 24 Oct 2024.

Written by Jia Chen.

Swift Playgrounds for iPad app icon

Sample Project

Image Playground Sheets

Last updated on 24 Oct 2024.

Written by Jia Chen.

Swift Playgrounds for iPad app icon

Sample Project

Scroll Down

On this page

On this page

Beta Features
Apple Intelligence features, like Image Playground, are available on iPhone 15 Pro, iPhone 15 Pro Max, or newer devices running iOS 18.2 or later.

Presenting Image Playground

In order to present the Image Playground image creation interface, you need to

  1. Import Image Playground

  2. Use the Image Playground sheet modifier to display a sheet

  3. Display the image from the returned URL

import ImagePlayground
struct ContentView: View {
    
    @State private var isImagePlaygroundPresented = false
    @State private var imageURL: URL?

    @Environment(\.supportsImagePlayground) private var supportsImagePlayground
    
    var body: some View {
        VStack {
            if let imageURL {
                AsyncImage(url: imageURL) { image in
                    image
                        .resizable()
                        .scaledToFit()
                } placeholder: {
                    ProgressView()
                }
                AsyncImage(url: imageURL)
            }
            
            if supportsImagePlayground {
                Button("Show Image Playground", systemImage: "apple.image.playground") {
                    isImagePlaygroundPresented.toggle()
                }
            } else {
                Text("Image Playground is not supported on this device.")
                    .multilineTextAlignment(.center)
            }
        }
        .padding()
        .imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented) { url in
            imageURL = url
        }
    }
}

Image Playground Sheet

The Image Playground sheet functions like the normal sheet modifier. It takes in a Binding boolean isPresented value and returns a URL to the image.

In order to implement it, you will need

  1. A State boolean variable to manage the presentation of the Image Playground sheet.

  2. To pass that variable as a Binding value into the Image Playground sheet

  3. To set the variable to true, in order to present it

@State private var isImagePlaygroundPresented = false

You can attach the Image Playground Sheet modifier to any visible view, in this case, the Button that presents the sheet.

Button("Imagine…", systemImage: "apple.image.playground") {
    isImagePlaygroundPresented.toggle()
}
.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented) { url in
}

Displaying an Image from URL

The Image Playground Sheet returns a URL to locate the image through the completion handler (the curly braces at the end). In order to display the image, you can use an Async Image to load it from a URL

Loading Image from URL

To load an image from a URL, you will need

  1. A State variable to store the image URL. This variable should be an Optional value so it can be set to nil when no image has been generated.

  2. To set the image URL variable to the returned URL in the Image Playground sheet's completion handler

  3. To display the image from a URL with Async Image.

@State private var imageURL: URL
Button("Imagine…", systemImage: "apple.image.playground") {
    isImagePlaygroundPresented.toggle()
}
.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented) { url in
    imageURL = url
}

You can use an if-let Optional binding to unwrap the imageURL and display the Async Image.

if let imageURL {
    AsyncImage(url: imageURL)
} else {
    Text("No image to show")
}

Customizing the Image

Within an Async Image, you can customize the appearance of the image. In the following example, the image is scaled to fit the view.

AsyncImage(url: imageURL) { image in
    image
        .resizable()
        .scaledToFit()
} placeholder: {
}

Creating a Placeholder

Using the placeholder parameter, you can supply the Async Image with a placeholder view to display. Using a Progress View allows you to create the indeterminate spinning indicator while waiting.

AsyncImage(url: imageURL) { image in
    image
        .resizable()
        .scaledToFit()
} placeholder: {
    ProgressView()
}

Remember to Move the Image

The image is stored in a temporary location after creation. If you intend on persisting the image, you can save the image to a different location by moving it out.

In the following example, the completion handler is modified to save the image permanently into a new location within the app's documents directory.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented) { url in
    let newLocation = URL.documentsDirectory.appendingPathComponent("image.png")
    try? FileManager.default.moveItem(at: url, to: newLocation)
    imageURL = newLocation
}

Checking for Availability

You can use the .supportsImagePlayground environment variable to check if Image Playground is available. It returns a boolean value.

@Environment(\.supportsImagePlayground) private var supportsImagePlayground

With conditional rendering, you can show and hide a button or prompt based on whether or not Image Playground is available.

if supportsImagePlayground {
    Button("Imagine…", systemImage: "apple.image.playground") {
        isImagePlaygroundPresented.toggle()
    }
}

You can also add an else clause to display a view if Image Playground is not available. In the following example, a simple Text.

if supportsImagePlayground {
    Button("Imagine…", systemImage: "apple.image.playground") {
        isImagePlaygroundPresented.toggle()
    }
} else {
    Text("Imagine… having Image Playground available 😔")
}

Downloading Image Playground

If Image Playground is not downloaded, or the user is still on the waitlist, the Image Playground Sheet will present the sheet where the user can see their waitlist status or sign up to join the waitlist.

Concepts

Concepts are text elements that specify the content to include in the image. You can use it to add pieces of text describing the image you want the user to create.

The user can override the concepts provided from within the Image Playground sheet.

Creating a Concept

There are two kinds of concepts, text and extracted.

  • Text concepts are suitable for short strings, like single words or sentences

  • Extracted concepts are suitable for longer strings, like paragraphs or documents.

Text Concepts

When you supply a Text Concept to the Image Playground, the system will try to add this string to the playground to use it as a prompt.

ImagePlaygroundConcept.text("A rabbit drinking hot chocolate")

Extracted Concepts

When you supply an Extracted Concept to the Image Playground, the system will try to extract important or interesting concepts from the string and add them to the playground so that each concept becomes an input prompt.

You can choose to add a title with the title parameter.

ImagePlaygroundConcept.extracted(from: "...")
ImagePlaygroundConcept.extracted(from: "...", title: "The Bee Movie Script")

Using Concepts

Single Text Concept

You can supply a single Text Concept by supplying the string itself into the concept parameter.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented,
                      concept: "A rabbit jumping on a tree.") { url in
    imageURL = url
}

Using Any Concept(s)

The following example is a more flexible implementation, allowing you to use any number of Text and Extracted concepts. You will have to supply the Image Playground with an array of Image Playground Concepts.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented,
                      concepts: [
                        .text("A rabbit drinking hot chocolate"), 
                        .extracted(from: "...", title: "The Bee Movie Script")
                      ]) { url in
    imageURL = url
}

Using a Source Image

You can specify an existing image to provide as the source image for creating a new image. The user can override the provided image and choose different images within the Image Playground sheet. If you do not provide a source image, Image Playground creates one based solely on the concepts.

In the following example, a concept and source image is used together to supply both to the user within the Image Playground sheet.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented,
                      concept: "A rabbit jumping on a tree.",
                      sourceImage: Image("Source Image")) { url in
    imageURL = url
}

You can choose to omit the concept parameter as well. Without any provided concepts, the user can select from a series of system concepts to customize their image.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented,
                      sourceImage: Image("Source Image")) { url in
    imageURL = url
}

Finally, you can also provide a source image as a URL.

.imagePlaygroundSheet(isPresented: $isImagePlaygroundPresented,
                      sourceImageURL: myURLValue) { url in
    imageURL = url
}

© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.

© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.

© 2024 Tinkertanker Pte Ltd / Swift Accelerator. All rights reserved.