Swift 4.1 Playground中CIImage加载URL图片报错‘Failed to convert UIImage to PNG’求助
Hey there, let's break down why you're hitting this error and how to fix it quickly.
The Root Cause
Your code tries to initialize a CIImage directly from a remote URL using CIImage(contentsOf:), but this method isn't designed to handle remote network resources smoothly. When dealing with a JPG from a URL, the underlying implementation attempts to convert the image to PNG under the hood—which fails because the remote resource isn't being loaded and decoded properly first.
The Solution
Instead of passing the remote URL directly to CIImage, first download the image data, then initialize the CIImage from that raw data. Also, since we're working in a Playground, we need to enable indefinite execution to let the asynchronous network request finish.
Here's the corrected code:
import UIKit import PlaygroundSupport // Let the Playground wait for async tasks to finish PlaygroundPage.current.needsIndefiniteExecution = true let url = URL(string: "https://placekitten.com/500/500")! // Use URLSession to download the image data asynchronously URLSession.shared.dataTask(with: url) { data, response, error in guard let imageData = data, error == nil else { print("Oops, failed to download image: \(error?.localizedDescription ?? "Unknown error")") PlaygroundPage.current.finishExecution() return } // Initialize CIImage from the downloaded data if let ciImage = CIImage(data: imageData) { print("Successfully created CIImage from the JPG! 🎉") // You can work with ciImage here } else { print("Failed to decode image data into CIImage") } // Tell the Playground we're done PlaygroundPage.current.finishExecution() }.resume()
Why This Works
- Downloading first: By fetching the raw JPG data first, we ensure we have a complete, valid image file before trying to decode it with
CIImage. This avoids the forced PNG conversion that was causing your error. - Async execution: Playgrounds terminate by default once the main code finishes running. Enabling
needsIndefiniteExecutionkeeps the playground alive until we callfinishExecution(), letting the network request complete.
Alternative (Synchronous, Not Recommended)
If you want a quick synchronous test (note: this is bad practice for real apps, as it blocks the main thread), you can load the data directly:
import UIKit let url = URL(string: "https://placekitten.com/500/500")! do { let imageData = try Data(contentsOf: url) if let ciImage = CIImage(data: imageData) { print("Success!") } else { print("Failed to decode image") } } catch { print("Error loading data: \(error)") }
Stick with the asynchronous approach for any production code—your users will thank you for keeping the app responsive.
内容的提问来源于stack exchange,提问作者Brett

