printdotio / printio-ios-sdk

SDK that enables the printing of any photo, from any source, onto any product!
Other
20 stars 11 forks source link

Cached images never deleted #489

Closed jordansorensen closed 6 years ago

jordansorensen commented 8 years ago

It seems like the print.io SDK caches images locally on the device but never cleans up this cache. This causes apps using the print.io SDK to grow, taking up gigabytes of device storage.

These cached images seem to be created when the user reaches the "Image Quantity and Cropping" screen, and they're stored in AppData/Library/Caches/PrintMeCache. (I'm using setImages and providing a list of file names - I'm not sure if other photo sources behave the same way).

  1. In Settings > General > Storage & iCloud Usage > Manage Storage, observe how much storage the app is using.
  2. In the app, save images locally (50 should be enough to make the issue obvious) and pass their filenames to print.io's setImages. In PrintIOWidgetOnCloseWithData:(NSDictionary *)data, delete these images.
  3. [printIO goToProductId:PRODUCT_PRINTS()];
  4. Launch print.io.
  5. "Make It!", select any print material and size, wait for "Loading" and "Processing" to complete.
  6. Hit "<" until you've exited print.io.
  7. If you go back to "Manage Storage" notice that the app is now using much more storage. Restarting the app, clearing out print.io cart, etc does not reduce this storage - it is there forever. In Xcode, if you look at what the app is storing ("Devices" > device > gear icon > "Download Container", you'll see a file for each image in AppData/Library/Caches/PrintMeCache.
perisicboro commented 8 years ago

@jordansorensen We can't delete all cached images, but def we will some of them. This will be fixed in next sdk version.

jordansorensen commented 8 years ago

Great, thanks. I'm a little confused by your statement that not all cached images can be deleted, but I'll wait for the next SDK version.

perisicboro commented 8 years ago

@jordansorensen Fixed in next sdk version. All cached data cleared after successful order.

jordansorensen commented 8 years ago

That's great; I'll keep my eye out for the next version. What about if the dialog is brought up but the user does not add any items to their cart nor complete their order?

jordansorensen commented 8 years ago

When will the next SDK version with this fix be released?

tobiasfrier commented 8 years ago

@jordansorensen It will be released tomorrow.

jordansorensen commented 8 years ago

This issue still exists in the latest version of the SDK (1.6.0).

When you follow the steps above (in which you exit before adding any item to your cart), print.io still caches and never deletes images.

It is possible that what you said is true ("All cached data cleared after successful order."). However, I cannot test that because of issue #490. In addition, just deleting those images after a successful order is not enough. I expect it to be a somewhat regular case that users start an order they decide not to place, and I can't release my app with the print.io SDK if it's going to unrecoverably eat hundreds of megs of storage from my users.

tobiasfrier commented 8 years ago

@jordansorensen

I will make sure issue #489 gets resolved in a manner relevant to this use case.

jordansorensen commented 8 years ago

Great, thanks Tobias!

jordansorensen commented 8 years ago

My preliminary testing seems to indicate this has been fixed in 1.6.10 - fantastic! I'll do a little more testing to confirm and then close this issue.

jordansorensen commented 8 years ago

Unfortunately there are still common use cases that cause images to be "cached" permanently. For example, if the user adds photos to their cart and then deletes it, those images are never deleted. If the app terminates while the print.io controller is visible, any cached images are never deleted (for example, if the user force-kills the app, if the app crashes, or if iOS terminates the app due to memory pressure when the user is switching between apps). I've written some code to work around this issue myself. I call this method (1) after the print.io controller closes, and (2) every time the app launches (to catch the termination case).

+ (void)cleanupAfterPrintIO {
    // If print.io has nothing in the shopping cart, it shouldn't need to cache
    // any photos.
    // Used to work around bugs where print.io does not clean up after itself.
    if ([PrintIO numberOfItemsInShoppingCart] == 0) {
        NSFileManager* fileManager = [NSFileManager defaultManager];
        NSArray<NSURL*>* searchURLs = [fileManager URLsForDirectory:NSCachesDirectory
                                                          inDomains:NSUserDomainMask];
        for (NSURL* searchURL in searchURLs) {
            // In each potential cache directory that iOS gives us, look to see
            // if there's a PrintMeCache directory.
            NSURL* printIOCache = [searchURL URLByAppendingPathComponent:@"PrintMeCache"];
            if ([fileManager fileExistsAtPath:[printIOCache path] isDirectory:nil]) {
                // print.io does have a cache here - delete its contents.
                NSArray<NSURL*>* directoryContents = [fileManager contentsOfDirectoryAtURL:printIOCache
                                                                   includingPropertiesForKeys:nil
                                                                                      options:0
                                                                                        error:nil];
                for (NSURL* fileURL in directoryContents) {
                    [fileManager removeItemAtURL:fileURL error:nil];
                    NSLog(@"Removed print.io file at '%@'", fileURL);
                }
            }
        }
    }
}