Swift 3 - Save image and load image with document directory

Hi there, I've been looking for sample codes on how to save image and load image with document directory, but most of it that I found couldn't be use with Swift 3.. Is there anyone could refer me to a link or can help me out??

Replies

I'm currently trying to change the code usable to Swift 3 by Dharmesh Kheni from

http://stackoverflow.com/questions/30953070/get-image-name-uiimagepickercontroller-in-swift


But I don't actually know how to do it, all I need is some tips or link on how to do it.. Help please..

Here’s a trivial example of writing an image to disk as a PNG and then reading it back.

let imageData = UIImagePNGRepresentation(image)!
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let imageURL = docDir.appendingPathComponent("tmp.png")
try! imageData.write(to: imageURL)

let newImage = UIImage(contentsOfFile: imageURL.path)!

I’ve left out all the error handling. Specifically, you really want to handle any errors you get writing (line 4) or reading (line 6) the image.

This uses a PNG representation, which is convenient but may not be the best option. For JPEG you could use

UIImageJPEGRepresentation
instead. For anything more complex, or for more control in general, check out the ImageIO framework.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

This is good, thanks.

Now if you want to skipBackup (addSkipBackupAttributeToItemAtURL...) for this file

what would that look like in Swift 3 ?

There's an example for Swift 2 at https://developer.apple.com/library/content/qa/qa1719/_index.html and in Xcode docs.


Try this translation to Swift 3:


func addSkipBackupAttributeToItem(atPath path: String) -> Bool {
   
    var url = URL(fileURLWithPath: path)
   
    assert(FileManager.default.fileExists(atPath: path), "File \(path) does not exist")
   
    var success: Bool
    do {
        var resourceValues = URLResourceValues()
        resourceValues.isExcludedFromBackup = true
        try url.setResourceValues(resourceValues)
        success = true
    } catch let error as NSError {
        success = false
        print("Error excluding \(url.lastPathComponent) from backup \(error)");
    }
   
    return success
}


URL is a struct (NSURL is a class), hence the var so its resource values can be modified.

Great, This helps a lot.

I had read Technical Q&A QA1719 and some post but I was being a little slow on the uptake.

I did an in line version too;


let directory = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

var storeUrl = directory.appendingPathComponent("MyApp.sqlite")

var resourceValues = URLResourceValues()

resourceValues.isExcludedFromBackup = true

try! storeUrl.setResourceValues (resourceValues)

print("excluding \(storeUrl.lastPathComponent) from backup ")


How's that.

Thanks.

Why not create a function which can be reused and which will make the code that calls it easier to read and maintain?

Also, why use "try!" which will result in your program crashing if an error is thrown?

Ok, you are right about the try! I'll fix that.

But when I use func addSkipBackupAttributeToItem(atPath path: String)...

where do I call it from?


if I call from the AppDelegate ...didFinishLaunchingWithOptions.. I get a Swift Compiler Warning-- 'Result of call to 'addSkipBackupAttributeToItem(atPath:)' is unused'


If called for after;

var storeUrl = directory.appendingPathComponent()

I get an Compiler Error -- Use of instance member 'addSkipBackupAttributeToItem' on type 'AppDelegate'; did you mean to use a value of type 'AppDelegate' instead?


That why I went with in-line.

Goldsdad gave you a very literal translation of that QA1719 method, but that method does not follow current Swift or API conventions:


— The method name does not follow current Swift naming conventions.


— It should not have a path string parameter. The parameter should already be a URL.


— It should not return a Bool result, but should throw an error if it fails.


— It should not test for the existence of the file, but should simply go ahead and try setting the resource values, which will (correctly) throw an error if the file does not exist.


— It doesn't need to handle the error, since the caller should handle it.


Putting those things together, the translation becomes this:


func addSkipBackupAttribute (toItemAt url: URL) throws { 
     var resourceValues = URLResourceValues() 
     resourceValues.isExcludedFromBackup = true 
     try url.setResourceValues(resourceValues) 
}


You can call this from your app delegate's "didFinishLaunching…" method. Because it can throw, you will need to use "try!" (to crash if it fails) or "try" (inside a do/catch block), depending on how you want to handle any error.

Similar to Quincey's response, you can add the following extension to URL:


extension URL {
    mutating func excludeFromBackup(_ value: Bool) throws {    
        var resourceValues = URLResourceValues()
        resourceValues.isExcludedFromBackup = value
        try self.setResourceValues(resourceValues)
    }
}


Then when you have a URL for the item that's not to be backed up, you can write something like:


do {
    try someURL.excludeFromBackup(true)
} catch {
    ...
}

Did you solve the issue?

Have you solved this? I also want to do the same task , Please Help!