Swift で以下のような特殊文字を文字列リテラルに含める時、皆さんどうしてますか??
-
"
: ダブルクォーテーション -
'
: シングルクォーテーション -
\
: バックスラッシュ - tab: タブ文字
- return: 改行文字 (
\n
) - : null 文字
- 先頭: キャリッジリターン
例えば、以下のような JSON 文字列を文字列リテラルに入れようとしても上手く行かないですよね。
{ "name": "Daichi", "age": 23 }
let jsonString: String = "{ "name": "Daichi", "age": 23 }"
// コンパイルエラー (ダブルクォーテーションが文字列の終わりと認識されちゃう)
この記事では、
- バックスラッシュでエスケープする方法
- Extended String Delimiters を使う方法
の 2 つの対処法を紹介します。
\
バックスラッシュでエスケープする方法
Swift における特殊文字のエスケープは \
(バックスラッシュ) を特殊文字の前に記述することで、文字列リテラル内で表現できます。
- ダブルクォーテーション →
\"
- シングルクォーテーション →
\'
- バックスラッシュ →
\\
- タブ文字 →
\t
- 改行文字 →
\n
- null 文字 →
\0
- キャリッジリターン →
\r
先程の JSON をこの方法を使って String
型変数に突っ込むとこうなります。
let jsonString: String = "{ \"name\": \"Daichi\", \"age\": 23 }"
print(jsonString)
// This wiil print out "{ "name": "Daichi", "age": 23 }"😁.
これによって文字列内のダブルクォーテーションがエスケープされ、一つの文字列として認識されます。
Extended String Delimiters を使う方法
Swift には Extended String Delimiters という拡張文字列リテラルが用意されています。
これは #
(シャープ、数字文字) を使った方法です。
文字列リテラルを #
で囲むことで特殊文字がそのまま文字として利用できます。
let jsonString: String = #"{ "name": "Daichi", "age": 23 }"#
print(jsonString)
// This wiil also print out "{ "name": "Daichi", "age": 23 }"😁.
複数行リテラルでも同じです。
let string: String = #"""
{ "name": "Daichi", "age": 23 }
"""#
いちいち \
でエスケープしなくていいので、ダミー用の JSON を用意するときとか便利じゃないですか!?
文字列リテラルに変数を含めるには?
Extended String Delimiters を使うと、普段どおり変数を文字列リテラルに含めようとしても、\
がエスケープされてしまうので埋め込めません。
let name = "Daichi"
let age = 23
let jsonString = #"{ "name": "\(name)", "age": \(age) }"#
print(jsonString)
// This wiil print out "{ "name": "\(name)", "age": \(age) }"🥺.
この場合は、バックスラッシュと開き括弧の間に #
を入れて \#(変数)
という風に書くと期待の結果が得られます。
let name = "Daichi"
let age = 23
let jsonString = #"{ "name": "\#(name)", "age": \#(age) }"#
print(jsonString)
// This wiil print out "{ "name": "Daichi", "age": 23 }"😆.
やったぜ。
おわり
個人的には
- 特殊文字が多い時: Extended String Delimiters を使う
- 変数が多い時: バックスラッシュでエスケープする
のように使い分けてあげると、文字列リテラルがあるコードをパッと見た時にノイズが少なくて良いのかな〜〜なんて思います。