Сохраняя изображение, а затем загружая его в Swift (iOS)
Я сохраняю изображение с помощью saveImage.
func saveImage (image: UIImage, path: String ) -> Bool{
let pngImageData = UIImagePNGRepresentation(image)
//let jpgImageData = UIImageJPEGRepresentation(image, 1.0) // if you want to save as JPEG
print("!!!saving image at: \(path)")
let result = pngImageData!.writeToFile(path, atomically: true)
return result
}
Новая информация:
Сохранение файла не работает должным образом ( "[-] ERROR SAVING FILE" печатается) -
// save your image here into Document Directory
let res = saveImage(tempImage, path: fileInDocumentsDirectory("abc.png"))
if(res == true){
print ("[+] FILE SAVED")
}else{
print ("[-] ERROR SAVING FILE")
}
Почему функция saveImage не сохраняет изображение? Права доступа?
Старые данные:
В отладочной информации говорится:
!!!saving image at: file:///var/mobile/Applications/BDB992FB-E378-4719-B7B7-E9A364EEE54B/Documents/tempImage
Затем я извлекаю это местоположение, используя
fileInDocumentsDirectory("tempImage")
Результат правильный.
Затем я загружаю файл, используя этот путь
let image = UIImage(contentsOfFile: path)
if image == nil {
print("missing image at: \(path)")
}else{
print("!!!IMAGE FOUND at: \(path)")
}
Путь верен, но сообщение "отсутствует изображение в..". Является ли файл каким-то недосягаемым или не сохраненным? Что может быть причиной такого поведения?
Я тестирую этот код на iphone 4 с ios 7 и iphone 5 с симулятором ios 7.
Изменить:
1. Функция fileInDocumentsDirectory
func fileInDocumentsDirectory(filename: String) -> String {
let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let fileURL = documentsURL.URLByAppendingPathComponent(filename).absoluteString
return fileURL
}
Ответы
Ответ 1
Эта функция сохранит изображение в папке документов:
func saveImage(image: UIImage) -> Bool {
guard let data = UIImageJPEGRepresentation(image, 1) ?? UIImagePNGRepresentation(image) else {
return false
}
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do {
try data.write(to: directory.appendingPathComponent("fileName.png")!)
return true
} catch {
print(error.localizedDescription)
return false
}
}
Использовать:
let success = saveImage(image: UIImage(named: "image.png")!)
Эта функция получит это изображение:
func getSavedImage(named: String) -> UIImage? {
if let dir = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) {
return UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent(named).path)
}
return nil
}
Использовать:
if let image = getSavedImage(named: "fileName") {
// do something with image
}
Ответ 2
iOS 12+ Swift 5.1
iOS 12 представила некоторые изменения API.
func saveImage(imageName: String, image: UIImage) {
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileName = imageName
let fileURL = documentsDirectory.appendingPathComponent(fileName)
guard let data = image.jpegData(compressionQuality: 1) else { return }
//Checks if file exists, removes it if so.
if FileManager.default.fileExists(atPath: fileURL.path) {
do {
try FileManager.default.removeItem(atPath: fileURL.path)
print("Removed old image")
} catch let removeError {
print("couldn't remove file at path", removeError)
}
}
do {
try data.write(to: fileURL)
} catch let error {
print("error saving file with error", error)
}
}
func loadImageFromDiskWith(fileName: String) -> UIImage? {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
let image = UIImage(contentsOfFile: imageUrl.path)
return image
}
return nil
}
Ответ 3
подробности
- Версия Xcode 10.2 (10E125), Swift 5
Решение
// save
extension UIImage {
func save(at directory: FileManager.SearchPathDirectory,
pathAndImageName: String,
createSubdirectoriesIfNeed: Bool = true,
compressionQuality: CGFloat = 1.0) -> URL? {
do {
let documentsDirectory = try FileManager.default.url(for: directory, in: .userDomainMask,
appropriateFor: nil,
create: false)
return save(at: documentsDirectory.appendingPathComponent(pathAndImageName),
createSubdirectoriesIfNeed: createSubdirectoriesIfNeed,
compressionQuality: compressionQuality)
} catch {
print("-- Error: \(error)")
return nil
}
}
func save(at url: URL,
createSubdirectoriesIfNeed: Bool = true,
compressionQuality: CGFloat = 1.0) -> URL? {
do {
if createSubdirectoriesIfNeed {
try FileManager.default.createDirectory(at: url.deletingLastPathComponent(),
withIntermediateDirectories: true,
attributes: nil)
}
guard let data = jpegData(compressionQuality: compressionQuality) else { return nil }
try data.write(to: url)
return url
} catch {
print("-- Error: \(error)")
return nil
}
}
}
// load from path
extension UIImage {
convenience init?(fileURLWithPath url: URL, scale: CGFloat = 1.0) {
do {
let data = try Data(contentsOf: url)
self.init(data: data, scale: scale)
} catch {
print("-- Error: \(error)")
return nil
}
}
}
использование
// save image (way 1)
let path = "photo/temp/album1/img.jpg"
guard let img = UIImage(named: "img"),
let url = img.save(at: .documentDirectory,
pathAndImageName: path) else { return }
print(url)
// get image from directory
guard let img2 = UIImage(fileURLWithPath: url) else { return }
// save image (way 2)
let tempDirectoryUrl = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(path)
guard let url2 = img2.save(at: tempDirectoryUrl) else { return }
print(url2)
Результаты проверки
откройте каталог симулятора iOS
Ответ 4
Вы должны сохранить имя изображения с расширением, чтобы ваш путь был таким,
///var/mobile/Applications/BDB992FB-E378-4719-B7B7-E9A364EEE54B/Documents/tempImage.png
И второе, замените ниже строку,
let result = pngImageData!.writeToFile(path, atomically: true)
с
let result = pngImageData!.writeToFile(path, atomically: false)
Вам нужно установить false как параметр atomically
.
атомарно:
Если значение true, данные записываются в файл резервной копии, а затем - при отсутствии ошибок - файл резервной копии переименовывается в имя, указанное в пути; в противном случае данные записываются непосредственно в путь.
Надеюсь, это поможет:)
Ответ 5
Если вы хотите загрузить изображение с сервера, вы можете сделать это ниже
let url = URL(string: "http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil
else { return }
DispatchQueue.main.async() { () -> Void in
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("apple.jpg")
print(paths)
fileManager.createFile(atPath: paths as String, contents: data, attributes: nil)
}}.resume()
Ответ 6
Комментарий Ashish имеет ключ к ответу. Если вы прочитали документы на UIImage(contentsOfFile:)
, они скажут
path Путь к файлу. Этот путь должен содержать имя файла расширение, которое идентифицирует тип данных изображения.
Вызов imageNamed
достаточно умен, чтобы попробовать расширения .png и .jpg, но вызов contentsOfFile
ожидает полного пути, включая расширение.
Ответ 7
Вам нужно создать каталог в папке "Документы", чтобы иметь возможность хранить файл.
Ответ 8
Swift 5
func saveImage(image: UIImage) -> Bool{
guard let data = image.jpegData(compressionQuality: 1) ?? image.pngData() else {
return false
}
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
return false
}
do{
try data.write(to: directory.appendingPathComponent("\(txtNom.text!).png")!)
print(directory)
print(data)
print("si se pudo")
return true
} catch {
print(error.localizedDescription)
return false
}
} // saveImage
Ответ 9
Я нашел решение на StackOverFlow некоторое время назад. Я не помню автора
Предполагая, что yourImage - UIImage()
let ciImage = yourImage!.ciImage
let context = CIContext()
let cgImage = context.createCGImage(ciImage!, from: ciImage!.extent)
let uiImage = UIImage(cgImage: cgImage!)
UIImageWriteToSavedPhotosAlbum(uiImage, self,
#selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
и эта функция
@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let error = error {
// we got back an error!
let ac = UIAlertController(title: "Save error", message: error.localizedDescription, preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
} else {
let ac = UIAlertController(title: "Saved!", message: "Your altered image has been saved to your photos.", preferredStyle: .alert)
ac.addAction(UIAlertAction(title: "OK", style: .default))
present(ac, animated: true)
}
}