NSCoding does not preserve the full UIIMage information for images loaded with imageNamed:

Originator:matej
Number:rdar://20256585 Date Originated:23-Mar-2015 11:26 AM
Status:Open Resolved:
Product:iOS Product Version:8.2
Classification:Serious Bug Reproducible:Always
 
Summary:

Serializing an image using NSKeyedArchiver produces different results depending on how the image was loaded. 

- For images loaded with imageNamed: the image data is not serialized (which prohibits us from deserializing the image in full later on). 
- Images loaded with imageWithContentsOfFile: get completely preserved. 

Steps to Reproduce:

Open the attached project and run it. Follow the onscreen instructions and compare the different displayed results. 

Expected Results:

The image would be fully preserved even when loading it using imageNamed:.

Actual Results:

Images loaded with imageNamed: do not get fully serialized when using NSKeyedArchiver. 

Regression:

Occurs on iOS 8.2. Also happens on iOS 7. 

Notes:

Using imageWithContentsOfFile: works. Drawing images loaded with imageNamed: into a new bitmap context and obtaining a new image from it also works.

Comments

Workaround

UIImage encodeWithCoder: serializes it's content differently based on whether the image is available in the system image cache or not. If the image can be referenced by name, the implementation just stores the image path under the "UIImageName" key. This however appears to be broken and the archived path is an empty string. It's possible to work around this by manually ensuring the correct path gets stored. In that case deserialization works as expected as that also handles this special case differently.

Even with this bug fixes, I would still argue that this behavior is incorrect. In some cases the application might have to preserve an image that will not be available in the application bundle at a later time (say after an app update, or if sending the archived data to a different application or application version). In that case deserialization would still fail. The image data should be saved in any case (except for perhaps Apple framework resources - but even that is debatable).

A simple workaround is to copy the image data into a new image by redrawing it.

UIGraphicsBeginImageContext(image.size); [image drawAtPoint:CGPointZero]; image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();

Sample project

http://cl.ly/0N0m1d1Y0T3Q


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!