В моем анимационном приложении я хочу сохранить анимацию в формате gif в приложении «Фотографии». Прямо сейчас код, который у меня есть, успешно сохраняет его в фотографии с первого раза, но после этого он генерирует ошибку (ошибка PHPhotosErrorDomain -1.) ФункцияgenerateGifFromImages, похоже, работает, потому что я могу найти все файлы gif в папке назначения, но (кроме того, что я это делаю впервые) они просто не сохраняются в фотографии.
Я использую этот код для создания GIF из массива изображений:
import UIKit
import MobileCoreServices
public class GIFFromImages {
public enum colorSpace {
case rgb
case gray
}
public init () {}
}
extension GIFFromImages {
public func makeFileURL(filename: String) -> URL {
let gifDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let gifFileURL = gifDirectory.appendingPathComponent(filename)
return gifFileURL
}
public func generateGifFromImages(images: [UIImage], fileURL: URL, colorSpace: colorSpace, delayTime: Double, loopCount: Int) {
let gifGroup = DispatchGroup()
var tempImages: [UIImage] = []
for image in images {
gifGroup.enter()
let imageWidth = UIScreen.main.bounds.width
let imageHeight = UIScreen.main.bounds.height
let imageRect: CGRect = CGRect(x:0, y:0, width: imageWidth, height: imageHeight)
let imageBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
let context = CGContext(data: nil, width: Int(imageWidth), height: Int(imageHeight), bitsPerComponent: 8, bytesPerRow: 0, space: CGColorSpaceCreateDeviceGray(), bitmapInfo: imageBitmapInfo.rawValue)
if let cgImg = image.cgImage {
//Set bg as white
context?.setFillColor(UIColor.white.cgColor)
context?.fill(imageRect)
context?.draw(cgImg, in: imageRect)
if let makeImg = context?.makeImage() {
let imageRef = makeImg
let newImage = UIImage(cgImage: imageRef)
tempImages.append(newImage)
gifGroup.leave()
}
}
}
gifGroup.notify(queue: .main) {
let gifFileProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: loopCount]] as CFDictionary
let gifFrameProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFDelayTime as String: delayTime]] as CFDictionary
if let url = fileURL as CFURL? {
if let destination = CGImageDestinationCreateWithURL(url, kUTTypeGIF, images.count, nil) {
CGImageDestinationSetProperties(destination, gifFileProperties)
for image in tempImages {
if let cgImage = image.cgImage {
CGImageDestinationAddImage(destination, cgImage, gifFrameProperties)
}
}
if !CGImageDestinationFinalize(destination) {
print("Failed to finalize the image destination")
}
}
}
}
}
}
И я вызываю его и сохраняю в фотографии с этой кнопки:
Button {
print("Saving animation titled: \(animation.title)")
var images: [UIImage] = []
for frame in animation.frames {
let image = try! PKDrawing(data: frame.frameData).generateThumbnail(scale: 1)
images.append(image)
}
let timestamp = Date().timeIntervalSince1970
let timestampString = String(format: "%.0f", timestamp)
let gifURL = gifManager.makeFileURL(filename: "\(timestampString).gif")
gifManager.generateGifFromImages(images: images, fileURL: gifURL, colorSpace: .rgb, delayTime: (1.0/Double(animation.framesPerSecond)), loopCount: 0)
// Save the generated GIF to the Photos library
PHPhotoLibrary.shared().performChanges({
// Check if the GIF file exists
if FileManager.default.fileExists(atPath: gifURL.path) {
print("GIF file exists at:", gifURL.path)
} else {
print("Error: GIF file does not exist at:", gifURL.path)
}
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: gifURL)
}) { success, error in
if success {
print("GIF saved successfully.")
} else {
print("Error saving GIF:", error?.localizedDescription ?? "Unknown error")
}
}
close()
} label: {
ZStack {
Rectangle()
.frame(width: 400, height: 100)
.foregroundColor(.accentColor)
.cornerRadius(30)
Text("Save GIF to Photos")
.foregroundStyle(.white)
.font(.title)
.bold()
}
}
@jnpdx спасибо. Изменение дает мне следующее: Ошибка сохранения GIF: Error Domain=PHPhotosErrorDomain Code=-1 "(null)" Есть ли способ интерпретировать это?
iOS не имеет встроенных возможностей для работы с анимированными GIF-файлами. Я бы вообще не ожидал, что в библиотеке фотографий можно будет хранить анимированный GIF-файл; это не фотография в каком-либо смысле, который может понять iOS. Я бы предложил сохранить его где-нибудь в другом месте.
@matt, спасибо, но я не думаю, что это проблема. В первый раз GIF сохраняется, как и ожидалось, и у меня есть другие приложения, которые позволяют сохранять GIF-изображения в фотографии.
Я нашел решение: я сделал имя файла одинаковым для всех файлов, которые я сохраняю (чтобы оно переопределяло последний файл вместо добавления дополнительного хранилища), затем я добавил обработчик завершения в функциюgenerateGifFromImages, а затем последовал этому ответу. чтобы заменить мой код для сохранения gif в фотографиях: Сохранить gif в библиотеке фотографий iOS в Swift
Вы почти никогда не захотите использовать
localizedDescription
. Распечатка всей ошибки даст вам больше информации.