简体   繁体   中英

Clearing UserDefaults.standard.data information doesn't actually delete it?

I saved a UIImage to UserDefaults via.data with this code, where the key equals "petPhoto1":

@IBAction func addPhotoButton(_ sender: Any) {
        
        let picker = UIImagePickerController()
        picker.allowsEditing = false
        picker.delegate = self
        picker.mediaTypes = ["public.image"]
        present(picker, animated: true)
        
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            image.storeInUserDefaults(for: "petPhoto\(activePet)")
            UserDefaults.standard.set("yes", forKey: "doesImageExist\(activePet)")
        }
        
        dismiss(animated: true, completion: nil)
    }

(unrelated stuff in between)

extension UIImage {
    func storeInUserDefaults(with compressionQuality: CGFloat = 0.8, for key:     String) {
    guard let data = self.jpegData(compressionQuality: compressionQuality) else { return }
    let encodedImage = try! PropertyListEncoder().encode(data)
    UserDefaults.standard.set(encodedImage, forKey: key)
    }
}

Now when I erase it like this:

UserDefaults.standard.set(nil, forKey: "petPhoto1")

I can still see that "Documents & Data" for my app under Settings is still full with the same size as the original image, indicating that it didn't actually delete it, even though it no longer displays when it gets loaded back from UserDefaults.

Can anyone figure out a way to fix this? Thanks!

By the way, in case it helps, here is other code related to this issue:

The code I use in the ImageViewController that I display the image after saving it:

@IBOutlet weak var imageView: UIImageView!

override func viewDidLoad() {
        super.viewDidLoad()
        
        activePet = UserDefaults.standard.string(forKey: "activePet")! // activePet = 1 (confirmed with debugging with other, unrelated code
        
        imageView.image = try? UIImage.loadFromUserDefaults(with: "petPhoto\(activePet)")
        
    }

extension UIImage {
    static func loadFromUserDefaults(with key: String) throws -> UIImage? {
         let activePet = UserDefaults.standard.string(forKey: "activePet")!
         guard let data = UserDefaults.standard.data(forKey: "petPhoto\(activePet)") else {
             return nil
         }
         do {
             let decodedImageData = try PropertyListDecoder().decode(Data.self, from: data)
             return UIImage(data: decodedImageData)
         } catch let error {
             throw error
         }
     }
}

When you do this:

UserDefaults.standard.set(nil, forKey: "petPhoto1")

The link between the key and the file saved will be removed synchronously. that means if you try to access the value for this key, it gives nil.

But this image needs to be cleared from storage too, that will be happening asynchronously [we don't have completion handler API support from apple to get this information].

Apple Documentation for reference:

At runtime, you use UserDefaults objects to read the defaults that your app uses from a user's defaults database. UserDefaults caches the information to avoid having to open the user's defaults database each time you need a default value. When you set a default value, it's changed synchronously within your process, and asynchronously to persistent storage and other processes.

What you can try:

First approch

Give some time for the file delete operation to get completed by OS. then try to access the image in the disk.

Second approch

Try observing to the changes in the directory using GCD. Refer: https://stackoverflow.com/a/26878163/5215474

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM