1

How would one programmatically save an image generated from a playground to the resources folder?

I have generated some photos through filters in my playground that I would like to save somehow. The resources folder seems like a good fit. What if I wanted to save the image to the desktop?

I've seen this done with saving images for apps, but I just want to save it to my desktop (or a specified folder in a specified location.)

pkamb
  • 33,281
  • 23
  • 160
  • 191
DaveNine
  • 391
  • 4
  • 21

4 Answers4

3

Create folder first in 'Documents' with name 'Shared Playground Data' otherwise app will give error.

SWIFT 5:

let image = // your UIImage
let filepath = playgroundSharedDataDirectory.appendingPathComponent("export.jpg")
let imagedata = image.jpegData(compressionQuality: 1.0)
try! imagedata?.write(to: URL.init(fileURLWithPath: filepath.path))
print("write to \(filepath)")
user1039695
  • 981
  • 11
  • 20
2

In Xcode 11, the folder is not in ~/Documents anymore for iOS playgrounds but buried deep in ~/Library/Developer/. You have to print the path and create the Shared Playground Data folder manually to save a file from a playground:

import PlaygroundSupport

// ...
let url = playgroundSharedDataDirectory.appendingPathComponent("example.png")
print(url)
try! image.pngData()!.write(to: url)
Ralf Ebert
  • 3,556
  • 3
  • 29
  • 43
1

Here's how to save it to the shared data directory:

Create a path to the image:

let path = XCPlaygroundSharedDataDirectoryURL.appendingPathComponent("export.jpg")!

(you may need to create the directory ~/Documents/Shared Playground Data/)

Then to save your output (in this case a CIImage from a filter)

let temp:CGImage = context.createCGImage(output, from: output.extent)!
let image = UIImage(cgImage: temp)
let data = UIImageJPEGRepresentation(image, 1.0)
try! data?.write(to: path)
svarrall
  • 8,545
  • 2
  • 27
  • 32
1

While the first answer helped point me in the right direction, the lack of ability to validate the required playgroundSharedDataDirectory path exists, the requirement to create that directory in order for the path to work, as well as force unwrapping (using !) the try can lead to frustration as well as drag out the process.

Here is a safer, more convenient solution that checks the name you provide for extra safety:

func writeImage(_ image: UIImage, name: String) {
    if name.isEmpty || name.count < 3 {
        print("Name cannot be empty or less than 3 characters.")
        return
    }
    guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
        print("No documents directory found.")
        return
    }
    let imagePath = documentsDirectory.appendingPathComponent("\(name).png")
    let imagedata = image.jpegData(compressionQuality: 1.0)
    do {
        try imagedata?.write(to: imagePath)
        print("Image successfully written to path:\n\n \(documentsDirectory) \n\n")
    } catch {
        print("Error writing image: \(error)")
    }
}

Call using:

writeImage(image, name: "MyNewImage")

A break down of what is happening:

  1. The method writeImage checks to see if the documents directory exists.

  2. If the documents directory does not exist (unlikely), stop process.

  3. If the documents directory exists, carry on and write the image to the path.

App Dev Guy
  • 5,396
  • 4
  • 31
  • 54