Issues with diacritics in filename on iOS when the system main language is not English

Hi, I'm encountering a weird issue on iOS that happens:

  • for files with diacritics in their name, like "Gòmez.pdf" or "Télé.mp4",
  • when the iPhone or iPad main language is not set to English,
  • if the file has been created with a relatively low-level Unix function like fopen() or copyfile().

Then, the file cannot be previsualized using QuickLook or opened using other apps. Most of the time it fails silently, but on some occasions I get the following error message: "You do not have permission to save the file "filename.pdf" in the folder "myFolder"".

The issue is present in, at least, iOS 16 and 26. It seems worse in iOS 26. It seems that all three conditions are required, I don't see the issue when the iPhone or iPad is set to use English as the main language. I also don't see the issue if I rename the files in the Files app.

I'm probably doing something wrong, but what can it be?

(it's kind of weird that my recommendation for users becomes: if you want to use international characters in your file names, you need to set the iPad language to English...)

Answered by DTS Engineer in 878470022

Thanks for that info.

Based on that, I created a small test project to exercise my normalisation theory:

  1. Using Xcode 26.3 on macOS 26.2, I created a new project.
  2. I added LSSupportsOpeningDocumentsInPlace and UIFileSharingEnabled to its Info.plist [1].
  3. I wired up a button to my test code, which I’ve pasted in at the end of this reply.
  4. I ran the app on an iOS 26.2 device.
  5. I tapped my test button. It was able to create the files.
  6. I switched to the Files app.
  7. And navigated to On My iPhone > My App Name.
  8. I tapped test, then test dec (naïve), then test pre (naïve). The first two worked; the last one failed as you described.

The difference between these file names is that the test dec (naïve) uses a decomposed ï (NFD) whereas test pre (naïve) uses a precomposed one (NFC). Clearly, that’s causing problems for Quick Look in the Files app and elsewhere.

So, there are two things for you to do here:

  • Please file a bug against iOS about this. It should be able to handle both normal forms equivalently. Once you’re done, post your bug number here and I’ll add my own comments to it.
  • In your app, you should be able to work around this by decomposing the paths that you pass to the low-level code that’s creating these files.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] I suspect that the latter is unnecessary, but I added it first and couldn’t be bothered removing it.


do {
    let docDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    
    print("will create")
    let content = Data("Hello Cruel World! \(Date.now)".utf8)
    
    func writeContent(to name: String) throws {
        var path = [UInt8](docDir.path.utf8)
        path.append(UInt8(ascii: "/"))
        path.append(contentsOf: name.utf8)
    
        try content.withUnsafeBytes { buf in
            let fd = path.withUnsafeBytes { pathBuf in
                open(pathBuf.baseAddress!.assumingMemoryBound(to: CChar.self), O_CREAT | O_WRONLY, 0o666)
            }
            guard fd >= 0 else {
                throw Errno(rawValue: errno)
            }
            defer { _ = close(fd) }
            let ok = write(fd, buf.baseAddress!, buf.count) >= 0
            if !ok {
                throw Errno(rawValue: errno)
            }
        }
    }
    
    try writeContent(to: "test.txt")
    try writeContent(to: "test pre (na\u{ef}ve).txt")
    try writeContent(to: "test dec (nai\u{308}ve).txt")
    
    print("did create")
} catch {
    print("did not create, error: \(error)")
}

It’s likely that this is related to the normalisation of the name used to create the file. However, it’s hard to be sure without seeing it in action. Reading through your description the bit that’s unclear is how you engage Quick Look or open the file with another app. Can you clarify either, or both, of those steps?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The short answer is that I tried everything (I could think of) and everything I tried fails.

  • in the Files app, simple tap on the file: opens QuickLook (iOS 16) or the Preview app (iOS 26) for files without diacritics in their name. Doesn't do anything for files with diacritics (it's like I didn't tap on the file at all).
  • in the Files app, long press on the file to get the contextual menu, scroll to Quick Look ("Coup d'œil" since I'm still in a non-English language), I get a blank screen that says "Document PDF".
  • opening the file using the documents browser from the Preview app (iOS 26) or PDF Viewer (iOS 26, iOS 16): does not display the file (it's like I didn't tap at all).
  • previewing the file from inside the app using UIDocumentInteractionController(url: url).presentPreview(animated: false): blank screen that says "Document PDF".
  • opening the file by calling another app from inside the app using an UIActivityViewController: nothing happens on iOS 26, I get the error message ("You do not have permission to save the file "filename.pdf" in the folder "myFolder"") with PDF Viewer on iOS 16.
Accepted Answer

Thanks for that info.

Based on that, I created a small test project to exercise my normalisation theory:

  1. Using Xcode 26.3 on macOS 26.2, I created a new project.
  2. I added LSSupportsOpeningDocumentsInPlace and UIFileSharingEnabled to its Info.plist [1].
  3. I wired up a button to my test code, which I’ve pasted in at the end of this reply.
  4. I ran the app on an iOS 26.2 device.
  5. I tapped my test button. It was able to create the files.
  6. I switched to the Files app.
  7. And navigated to On My iPhone > My App Name.
  8. I tapped test, then test dec (naïve), then test pre (naïve). The first two worked; the last one failed as you described.

The difference between these file names is that the test dec (naïve) uses a decomposed ï (NFD) whereas test pre (naïve) uses a precomposed one (NFC). Clearly, that’s causing problems for Quick Look in the Files app and elsewhere.

So, there are two things for you to do here:

  • Please file a bug against iOS about this. It should be able to handle both normal forms equivalently. Once you’re done, post your bug number here and I’ll add my own comments to it.
  • In your app, you should be able to work around this by decomposing the paths that you pass to the low-level code that’s creating these files.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] I suspect that the latter is unnecessary, but I added it first and couldn’t be bothered removing it.


do {
    let docDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    
    print("will create")
    let content = Data("Hello Cruel World! \(Date.now)".utf8)
    
    func writeContent(to name: String) throws {
        var path = [UInt8](docDir.path.utf8)
        path.append(UInt8(ascii: "/"))
        path.append(contentsOf: name.utf8)
    
        try content.withUnsafeBytes { buf in
            let fd = path.withUnsafeBytes { pathBuf in
                open(pathBuf.baseAddress!.assumingMemoryBound(to: CChar.self), O_CREAT | O_WRONLY, 0o666)
            }
            guard fd >= 0 else {
                throw Errno(rawValue: errno)
            }
            defer { _ = close(fd) }
            let ok = write(fd, buf.baseAddress!, buf.count) >= 0
            if !ok {
                throw Errno(rawValue: errno)
            }
        }
    }
    
    try writeContent(to: "test.txt")
    try writeContent(to: "test pre (na\u{ef}ve).txt")
    try writeContent(to: "test dec (nai\u{308}ve).txt")
    
    print("did create")
} catch {
    print("did not create, error: \(error)")
}

Thank you so much for the detailed explanation, and for the idea of a short-term solution.

I have filed a report: FB22138371

and in the meantime I'm using my_system(command.decomposedStringWithCanonicalMapping) instead of my_system(command) in my apps.

I have filed a report: FB22138371

Thanks.

decomposedStringWithCanonicalMapping should work here, but Kevin would probably advise that you go via URL and then use the withUnsafeFileSystemRepresentation(_:) method instead.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Issues with diacritics in filename on iOS when the system main language is not English
 
 
Q