EXIF metadata is stripped when creating an asset via addResource(with:.photo, data:) on iOS 26.6

Starting with iOS 26.6, saving an image to the photo library via PHAssetCreationRequest.addResource(with: .photo, data:, options:) appears to re-encode the image, dropping all EXIF metadata. The same code preserved metadata through iOS 26.5.

let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: .photo, data: image, options: nil)

I would like to know whether this change is intentional, and whether the file-based overload is the supported way to preserve an image's original metadata.

What we verified

  1. The bytes we hand to PhotoKit still contain the metadata.

  2. Setting contentType explicitly does not help. We resolved the type from the data and confirmed at runtime that it was non-nil (public.jpeg):

let options = PHAssetResourceCreationOptions()
if #available(iOS 26.0, *) {
    options.contentType = contentType   // verified: UTType.jpeg, not nil
}
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, data: imageData, options: options)
  • The resulting asset still has no EXIF.
  1. Writing the identical bytes to a temporary file and using the file-based overload preserves everything:
try imageData.write(to: temporaryFileURL, options: .atomic)

let options = PHAssetResourceCreationOptions()
options.shouldMoveFile = true
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, fileURL: temporaryFileURL, options: options)
  • Capture date, camera information and location are all intact.

We access the library with PHAccessLevel.addOnly.

Answered by DTS Engineer in 905766022

I can reproduce this on iOS 26.7, and I do not see it on iOS 27.0.

I ran the same test app on three iPad builds, saving a JPEG carrying DateTimeOriginal, LensModel, UserComment, TIFF Make and Model, and a GPS block:

  • iOS 26.5: addResource(with:.photo, data:options:) preserved every tag.
  • iOS 26.7: the same call dropped DateTimeOriginal, LensModel, UserComment, Make and Model. PHAsset.creationDate came back as the import time rather than the capture date, and PHAsset.location came back nil.
  • iOS 27.0: every tag preserved, and PHAsset.creationDate and PHAsset.location both matched the source.

The file-based overload returned the original bytes unchanged on all three versions, and shouldMoveFile made no difference to that. Setting contentType to UTType.jpeg made no difference on 26.7, which matches what you found.

One detail that may affect how you check this. On 26.7 the GPS block survived in the resource file with all four keys, while PHAsset.location was nil. The coordinates were still in the file even though the Photos database did not have them. PHAsset.location and the Photos info panel read the database rather than the file, so those two layers can disagree.

Since you are using PHAccessLevel.addOnly, your app cannot read the resource back to see which layer is affected. Requesting .readWrite in a debug build long enough to inspect the PHAssetResource data would separate the two.

I can reproduce this on iOS 26.7, and I do not see it on iOS 27.0.

I ran the same test app on three iPad builds, saving a JPEG carrying DateTimeOriginal, LensModel, UserComment, TIFF Make and Model, and a GPS block:

  • iOS 26.5: addResource(with:.photo, data:options:) preserved every tag.
  • iOS 26.7: the same call dropped DateTimeOriginal, LensModel, UserComment, Make and Model. PHAsset.creationDate came back as the import time rather than the capture date, and PHAsset.location came back nil.
  • iOS 27.0: every tag preserved, and PHAsset.creationDate and PHAsset.location both matched the source.

The file-based overload returned the original bytes unchanged on all three versions, and shouldMoveFile made no difference to that. Setting contentType to UTType.jpeg made no difference on 26.7, which matches what you found.

One detail that may affect how you check this. On 26.7 the GPS block survived in the resource file with all four keys, while PHAsset.location was nil. The coordinates were still in the file even though the Photos database did not have them. PHAsset.location and the Photos info panel read the database rather than the file, so those two layers can disagree.

Since you are using PHAccessLevel.addOnly, your app cannot read the resource back to see which layer is affected. Requesting .readWrite in a debug build long enough to inspect the PHAssetResource data would separate the two.

EXIF metadata is stripped when creating an asset via addResource(with:.photo, data:) on iOS 26.6
 
 
Q