I've learned that the Image IO Framework has changed syntactically since iOS 9 according to the documentation, however I have done my research and the following code seems to be correct. I have to procedures listed below; one procedure takes images and writes those images to the application's document folder as a gif. I can confirm this works as I can view the actually gif file if I go to the app's documents folder using iTunes. Despite this, in the second procedure where I attempt to read from that same file, an error is throw which states the file at that path does not exist. I have posted the code below.
class GifManager {
private func getDocumentsDirectory() -> URL? {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
}
public func generateGif(photos: [UIImage], filename: String) -> Bool {
if let docsDirectory = getDocumentsDirectory() {
let url = docsDirectory.appendingPathComponent(filename)
let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
let gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: 0.125]]
if let destination = CGImageDestinationCreateWithURL(url as CFURL, kUTTypeGIF, photos.count, nil) {
CGImageDestinationSetProperties(destination, fileProperties as CFDictionary?)
for photo in photos {
CGImageDestinationAddImage(destination, photo.cgImage!, gifProperties as CFDictionary?)
}
return CGImageDestinationFinalize(destination)
}
}
return false
}
public func saveGifToCameraRoll(filename: String) {
if let docsDirectory = getDocumentsDirectory() {
let fileUrl: URL = docsDirectory.appendingPathComponent(filename)
do {
let data = try Data(contentsOf: fileUrl)
if let _ = UIImage(data: data) {
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fileUrl)
}, completionHandler: {completed, error in
if error != nil {
print("error")
} else if completed {
print("completed")
} else {
print("not completed")
}
})
}
} catch let error {
print(error)
}
}
}
Swift 3.1, 4 and 5
For those wanting an updated version of the GIF generation function, I have included it here.
This function requires the ImageIO
and MobileCoreServices
import statements.
import ImageIO
import MobileCoreServices
Here is the function.
func generateGif(photos: [UIImage], filename: String) -> Bool {
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let path = documentsDirectoryPath.appending(filename)
let fileProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]
let gifProperties = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: 0.125]]
let cfURL = URL(fileURLWithPath: path) as CFURL
if let destination = CGImageDestinationCreateWithURL(cfURL, kUTTypeGIF, photos.count, nil) {
CGImageDestinationSetProperties(destination, fileProperties as CFDictionary?)
for photo in photos {
CGImageDestinationAddImage(destination, photo.cgImage!, gifProperties as CFDictionary?)
}
return CGImageDestinationFinalize(destination)
}
return false
}
EDIT:
It has a Bool
so you know you can safely use the file it creates.
if generateGif(arrayOfImages, "/myGIFfile.gif") {
// do something with gif
} else {
// failed to create and close the gif file
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With