質問: NSString(data:res, encoding: NSJapaneseEUCStringEncoding)! as String // 戻ってきた文字列の確認. print(myData) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } ``` このアドレスはエラーにならず。 関連項目。 https://ja.stackoverflow.com/questions/16426/nsurlrequestで日本語を使って-帰って来たデータを受け取るところでエラーになってしまうのはなぜか
回答: `NSString`のAPIでは、EUC-JPおよびSJISについて、JIS第2水準までの漢字しか対応していないのが原因です。 > > > > このアドレスはエラーにならず。 > > > この結果の中には、夔という第4水準漢字が含まれています。 これはブラウザでは正常に見ることができるのですが、`NSShiftJISStringEncoding`および`NSJapaneseEUCStringEncoding`のいずれにおいても、`NSString`にデコードおよびエンコードすることはできません。 UTF-8であれば扱うことができるのですが、Social IMEのAPIでは、 > > ・charset > > 出力の文字コードです。EUC-JPやSJISが指定できます。デフォルトはEUC-JPです。なお、入力文字列の文字コードは自動的に推定されます。 > > > Social IME かな漢字変換API ver 0.02 > > > とあるため、UTF-8で受け取ることができません。 以上を踏まえると、結果を受け取るには 1. アプリ側でEUC-JPまたはSJISから、UTF-8へ文字コードの変換を行う 2. 変換不可能な漢字が存在した場合、結果を無視する という対策が必要になります。1.の方法が望ましいですが、それを実現するには例えば`iconv`を使う方法がありますが、 * C言語のライブラリをSwiftで使う方法 * APIが非常にわかりにくい`iconv`を使う方法 * ポインタのポインタをSwiftで生成して渡す方法 も理解する必要があります。ですので、ここでは2.の例を記載します。 ``` let queryString = "キ" var result = [String]() if let searchWord = queryString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()), let url = NSURL(string:"http://www.social-ime.com/api/?string=\(searchWord)") { let request = NSURLRequest(URL: url); do { let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: nil) var word = [UInt8]() var byte = [UInt8](count: 1, repeatedValue: 0) let length = data.length / sizeof(UInt8); for var count = 0; count < length ; count+=sizeof(UInt8) { data.getBytes(&byte, range: NSRange(location: count, length: sizeof(UInt8))) if byte[0] == 0x09 { if let wordString = String(bytes: word, encoding: NSJapaneseEUCStringEncoding) where word.count != 0 { result.append(wordString) } word = [UInt8]() } else { word.append(byte[0]) } } } catch { fatalError() } } print(result) ``` Social IMEのAPIは変換結果をタブ文字(0x09)で分割して返すので、そのことを利用して変換可能な漢字だけを含む変換結果を`String`の配列に変換しています。