LoginSignup
7
9

More than 5 years have passed since last update.

iOS10.3 APFSの対処

Last updated at Posted at 2017-04-01

やらかしたので反省文

iOS10.3にてファイルシステムが HFS+からAPFSに強制変換されましたが
濁点など含むファイル名にてfopenなどの下位関数にアクセスする際
Stringなどからconst char* への変換は
UTF8String ではなく fileSystemRepresentation を使いましょう。

ざくっと調べた

検証コードを整えるのが面倒なので結果だけ

合成された普通のもの NFC : "だ" 3080 (1文字は1文字)
正規化分解NFD : "だ" 305F 3099 (濁点分割して検索なんかも楽しそうよね)

HFS+でもAPFSでもファイル名は正規化分割NFDされて保存される (前からそう)

HFS+では分割されていてもいなくても(NFD,NFC)同じNFDファイル名にアクセスできる、おそらくどこかでうまく処理してくれていたのだろう

APFSではfopenなどの下位関数はNFCそのままにアクセスされる、変換処理してくれない (ここが問題)

よってAPFSではNFC,NFDのファイル名が2つできたり、NFC名でアクセスした際ファイルが無いなどの問題が起こる
(これでNFCなファイルが出来るとbackupなんかでも問題起きたりするとか)

NSFileManagerなどの上位関数でのファイル処理は問題ない
(objc的に書いているけれども)swiftも問題は同じ

対処としては、ファイル名などは普通StringなりURLなりで持っていると思われ、
fopenなどの低位関数にてアクセスする際のファイル名は const char* に変換することになると思われるので、
このStringなりからconst char*への変換をUTF8StringではなくfileSystemRepresentation (これはファイルシステムに対応してNFDなりの処理をしてくれる)で行う。

CFStringNormalize((CFMutableStringRef)なにか, kCFStringNormalizationFormD);
でもNFD変換できるが、ここは素直にファイル系のAPIに従おう。

NSURLのメソッドなのでNSStringとかからなら
[[NSURL fileURLWithPath:self] fileSystemRepresentation];
てのでもよい。(相対パスからだと少し注意)

ファイルシステムとAPIの問題で、今までうまく処理していてくれただけに、バグと判断したくもなるヨナ。

ざくっとなので内容に関しては自分で確認してね。

追記
NFCなファイル名は存在するべきではないし、
ファイルのcreate/writeには上記に気をつけていれば問題ないがreadの場合、
NSFileManagerなどの上位関数ではNFCなファイル名のものは無いものとして処理される。
fileExistsAtPathなどではfalse
だがcontentsOfDirectoryAtPathではNFCなままリストアップされて返ってくる。
上位関数レベルで見ると、あるらしいけれどアクセスできないってファイルになるという。

そんなの作らなければいいのだけれど、windowsのiTunes転送だと、NFCなファイル名なまま作成されてしまう恐ろしい罠が。(あ、もうapple自身がやっちゃてるならバグよね)

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9