すべての文字列は、エンコーディングに依存しないUnicode文字で構成されている。
注意
Swift の String 型は、Foundation の NSString classへ橋渡しされており、Foundation をインポートすると、NSString のメソッドをキャストせずに使うことができる。
文字列リテラル
文字列リテラルは、二重引用符("
)で囲まれた文字のシーケンスです。
let someString = "Some string literal value"
複数行文字列リテラル
複数行にまたがる文字列が必要な場合は、複数行の文字列リテラル(”””)を使用します。
let quotation = """
The White Rabbit put on his spectacles. "Where shall I begin,
please your Majesty?" he asked.
"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
// ソースコードを読みやすくするために改行を使用したいが、改行を文字列の値の一部にしたくない場合は、バックスラッシュを用いる。
let softWrappedQuotation = """
The White Rabbit put on his spectacles. "Where shall I begin, \
please your Majesty?" he asked.
"Begin at the beginning," the King said gravely, "and go on \
till you come to the end; then stop."
"""
// 改行で開始または終了する複数行の文字列リテラル
let lineBreaks = """
This string starts with a line break.
It also ends with a line break.
"""
複数行の文字列をインデントして、周囲のコードと一致させることができます。
文字列リテラルの特殊文字
文字列リテラルには、次の特殊文字を含めることができます。
- エスケープされた特殊文字
\0
(null文字)、\\
(バックスラッシュ)、\t
(水平タブ)、\n
(改行)、\r
(キャリッジリターン)、\"
(二重引用符)および\'
(単一引用符) - 以下のように記述任意のUnicodeスカラー値、
\u{
nは}
、nは 1〜8桁の16進数
// エスケープされたダブルクオート
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
// "Imagination is more important than knowledge" - Einstein
// Unicode
let dollarSign = "\u{24}"
// $, Unicode scalar U+0024
let blackHeart = "\u{2665}"
// ♥, Unicode scalar U+2665
let sparklingHeart = "\u{1F496}"
// 💖, Unicode scalar U+1F496
複数行文字列リテラルは1つではなく3つの二重引用符を使用するため、"""
複数行の文字列にテキストを含めるには、少なくとも1つの引用符をエスケープします。
let threeDoubleQuotationMarks = """
Escaping the first quotation mark \"""
Escaping all three quotation marks \"\"\"
"""
// 結果
// Escaping the first quotation mark """
// Escaping all three quotation marks """
拡張文字列区切り文字
文字列リテラルを拡張区切り文字内に配置して、特殊文字を文字列に含めることができます。
let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#
// Here are three more double quotes: """
let teststr = #"Line 1\nLine 2"#
print(teststr)
// Line 1\nLine 2
空の文字列の初期化
空の文字列の初期化には、空の文字列リテラルを変数に割り当てるか、イニシャライザ構文で新しいインスタンスを初期化する。
var emptyString = "" // 空の文字列
var anotherEmptyString = String() // 空の文字列
文字列の可変性
特定のかどうかを示すString
変更された(またはされ得る変異、または(それは変更することができない場合)定数(この場合、それは変更することができる)変数に割り当てることによって)。
var variableString = "Horse"
variableString += " and carriage"
// 変更可能
let constantString = "Highlander"
constantString += " and another Highlander"
// 定数は変更できず、コンパイル時エラー
文字列は値型
String は値方です。Stringの値は、関数またはメソッドに渡されるとき、または定数または変数に割り当てられるときにコピーされる。
キャラクターの操作
ループで文字列を反復することにより、個々の文字にアクセスできます。
for character in "Dog!🐶" {
print(character)
}
// D
// o
// g
// !
// 🐶
// Character タイプアノテーションにより、文字列から文字を得る。
let exclamationMark: Character = "!"
// Stringに、Characterの配列を渡すことにより、文字列を得る。
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"
文字列と文字列の連結
String
値は、追加演算子()を使用して一緒に追加(または連結)して+
、新しいString
値を作成できます。
// + による連結
let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
// welcome now equals "hello there"
// += による連結
var instruction = "look over"
instruction += string2
// instruction now equals "look over there"
// String.appendによる連結
let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome now equals "hello there!"
複数行の文字列リテラルを使用して長い文字列の行を作成する場合は、最後の行を含め、文字列のすべての行を改行で終了する必要がある。例えば:
let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// Prints two lines:
// one
// twothree
let goodStart = """
one
two
"""
print(goodStart + end)
// Prints three lines:
// one
// two
// three
文字列補間
文字列補間は、定数、変数、リテラル、および式の組み合わせから値を文字列リテラル内に含めることにより、新しい値を構築する。文字列補間は、単一行と複数行の両方の文字列リテラルで使用できます。
バックスラッシュは、Option キー + ”¥” キーで入力する。
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
// 拡張文字列区切り文字を使用して、文字列補間の文字列を作成できる
print(#"Write an interpolated string in Swift using \(multiplier)."#)
// Prints "Write an interpolated string in Swift using \(multiplier)."
// 拡張区切り文字を使用する文字列内で文字列補間を使用するには、バックスラッシュの後のシャープ記号の数を、文字列の先頭と末尾のシャープ記号の数と一致させる。
print(#"6 times 7 is \#(6 * 7)."#)
// Prints "6 times 7 is 42."
Unicode
Unicodeスカラー値
Swiftの String 型はUnicodeスカラー値から構築されています。Unicodeスカラー値は、一意の21ビット数値です。
U+0061
は、 LATIN SMALL LETTER A
("a"
)
U+1F425
は、FRONT-FACING BABY CHICK
("🐥"
).
すべての21ビットUnicodeスカラー値が文字に割り当てられるわけではないことに注意してください。一部のスカラーは、将来の割り当てまたはUTF-16エンコーディングでの使用のために予約されています。文字に割り当てられているスカラー値には、通常、上記の例やなどの名前も付いています。
Extended Grapheme Clusters
SwiftのCharacter
型のすべてのインスタンスは、単一のextended grapheme clusterを表します。extended grapheme cluster は、1つ以上のUnicodeスカラーのシーケンスであり、組み合わせて、人間が読める単一の文字を生成します。
例えば、文字é
は、単一のUnicodeスカラーé
はé
(LATIN SMALL LETTER E WITH ACUTE
, or U+00E9
)として表すことができます。
また、同じ文字を1 対のスカラー 標準の文字 e (LATIN SMALL LETTER E
, or U+0065
), 及びそれに続く COMBINING ACUTE ACCENT
scalar (U+0301
) として表すこともできます。
どちらの場合も、文字é
は、extended grapheme cluster を表す単一の値として表されます。最初のケースでは、クラスターには単一のスカラーが含まれています。2番目のケースでは、2つのスカラーのクラスターです。
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}"
// e followed by eAcute is é, combinedEAcute is é
// ハングルの例
let precomposed: Character = "\u{D55C}" // 한
let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ
// precomposed is 한, decomposed is 한
let enclosedEAcute: Character = "\u{E9}\u{20DD}"
// 丸の中にé
// 地域インジケーターシンボルの例
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}"
// regionalIndicatorForUS is 🇺🇸
文字を数える
Character
文字列の値の数を取得するには、文字列のcount
プロパティを使用します。
let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
print("unusualMenagerie has \(unusualMenagerie.count) characters")
// Prints "unusualMenagerie has 40 characters"
SwiftがCharacter
値にextended grapheme cluster を使用するということは、文字列の連結と変更が常に文字列の文字数に影響を与えるとは限らないことに注意してください。
たとえば、新しい文字列を4文字の単語cafe
で初期化してから、文字列の末尾にCOMBINING ACUTE ACCENTU (U+0301
) を追加しても4文字となる。
var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in cafe is 4"
word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301
print("the number of characters in \(word) is \(word.count)")
// Prints "the number of characters in café is 4"
文字列へのアクセスと変更
文字列インデックス
String.Index
は、文字列のそれぞれの位置に対応した文字です。
上記のように、文字ごとに格納するメモリの量が異なる可能性があるためCharacter
、特定の位置にある文字を特定するには、その先頭または末尾から各Unicodeスカラーを反復処理する必要があります。このため、Swift文字列は整数値でインデックスを作成できません。
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
// G
greeting[greeting.index(before: greeting.endIndex)]
// !
greeting[greeting.index(after: greeting.startIndex)]
// u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index]
// a
startIndex
:最初Character
の位置
endIndex
:最後の文字の1つ後の位置
文字列の範囲Character
外のインデックスまたは文字列の範囲外のインデックスにアクセスしようとすると、ランタイムエラーが発生します。
greeting[greeting.endIndex] // Error
greeting.index(after: greeting.endIndex) // Error
indices
プロパティを使用して、文字列内の個々の文字のすべてのインデックスにアクセス。
for index in greeting.indices {
print("\(greeting[index]) ", terminator: "")
}
// Prints "G u t e n T a g ! "
挿入と削除
文字列の指定したインデックスに単一の文字を挿入するには、insert(_:at:)
メソッドを使用し、指定したインデックスに別の文字列の内容を挿入するには、insert(contentsOf:at:)
メソッドを使用します。
var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
remove(at:):指定されたインデックスの文字列から1文字を削除
removeSubrange(_:)
:指定された範囲の部分文字列を削除
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"
Substring
String.firstIndex(of:)
String.endIndex(of:)
let greeting = "Hello, world!"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning is "Hello"
// Convert the result to a String for long-term storage.
let newString = String(beginning)
上記の例でgreeting
は、文字列です。これは、文字列を構成する文字が格納されるメモリ領域があることを意味します。beginning
はSubstringなので、メモリを再利用します。対照的に、newString
は文字列です。Substringから作成された場合、独自のストレージを持っています。次の図は、これらの関係を示しています。
文字列の比較
Swiftは、テキスト値を比較する3つの方法を提供する。
- 文字列と文字の等価性
- プレフィックスの等価性
- サフィックスの等価性。
文字列と文字の等価性
比較演算子で説明されているように、文字列と文字の等価性は、== 演算子と!=演算子でチェックされます。
let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
print("等しい")
}
// Prints "等しい"
2つのString
値(または2つのCharacter
値)は、Extended Grapheme Clusters が標準的に等価である場合、等しいと見なされます。Extended Grapheme Clustersは、それらが舞台裏で異なるUnicodeスカラーから構成されている場合でも、同じ言語的意味と外観を持っている場合、標準的に同等です。
例えば、
LATIN SMALL LETTER E WITH ACUTE
(U+00E9
)
LATIN SMALL LETTER E
(U+0065
) followed by COMBINING ACUTE ACCENT
(U+0301
)
これらのExtended Grapheme Clustersはどちらも、é文字を表現する有効な方法であるため、同等であると見なされます。
// "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
// "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
print("These two strings are considered equal")
}
// Prints "These two strings are considered equal"
逆に、
LATIN CAPITAL LETTER A
(U+0041
, or "A"
) 英語で使用される
CYRILLIC CAPITAL LETTER A
(U+0410
, or "А"
) ロシア語で使用される
は、視覚的には似ていますが、同じ言語的意味はありません。
let latinCapitalLetterA: Character = "\u{41}"
let cyrillicCapitalLetterA: Character = "\u{0410}"
if latinCapitalLetterA != cyrillicCapitalLetterA {
print("These two characters are not equivalent.")
}
// Prints "These two characters are not equivalent."
注意
Swiftでの文字列と文字の比較は、ロケールに依存しません。
接頭辞と接尾辞が等しい
文字列に特定の文字列の接頭辞または接尾辞があるかどうかを確認するには、文字列のhasPrefix(_:)
およびhasSuffix(_:)
メソッドを使用する。
let romeoAndJuliet = [
"Act 1 Scene 1: Verona, A public place",
"Act 1 Scene 2: Capulet's mansion",
"Act 1 Scene 3: A room in Capulet's mansion",
"Act 1 Scene 4: A street outside Capulet's mansion",
"Act 1 Scene 5: The Great Hall in Capulet's mansion",
"Act 2 Scene 1: Outside Capulet's mansion",
"Act 2 Scene 2: Capulet's orchard",
"Act 2 Scene 3: Outside Friar Lawrence's cell",
"Act 2 Scene 4: A street in Verona",
"Act 2 Scene 5: Capulet's mansion",
"Act 2 Scene 6: Friar Lawrence's cell"
]
var act1SceneCount = 0
for scene in romeoAndJuliet {
if scene.hasPrefix("Act 1 ") {
act1SceneCount += 1
}
}
print("There are \(act1SceneCount) scenes in Act 1")
// Prints "There are 5 scenes in Act 1"
var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
if scene.hasSuffix("Capulet's mansion") {
mansionCount += 1
} else if scene.hasSuffix("Friar Lawrence's cell") {
cellCount += 1
}
}
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// Prints "6 mansion scenes; 2 cell scenes"
文字列のUnicode表現
Unicode文字列がテキストファイルまたはその他のストレージに書き込まれると、その文字列内のUnicodeスカラーは、コード単位と呼ばれる小さなチャンクにエンコードされます。これらには、UTF-8エンコード形式、UTF-16エンコード形式、UTF-32エンコード形式がある。
Swiftは、文字列のUnicode表現にアクセスするためのいくつかの異なる方法を提供します。for
– in
ステートメントを使用して文字列を反復処理し、Unicode extended grapheme clustersとして個々の値にアクセスできます。
または、String
他の3つのUnicode準拠の表現のいずれかの値にアクセスします。
- UTF-8コード単位のコレクション(文字列の
utf8
プロパティでアクセス) - UTF-16コード単位のコレクション(文字列の
utf16
プロパティでアクセス) - 21ビットUnicodeスカラー値のコレクション。文字列のUTF-32エンコード形式(文字列の
unicodeScalars
プロパティでアクセスされる)と同等
例
D, o, g, ‼ (DOUBLE EXCLAMATION MARK, or Unicode scalar U+203C), と 🐶 (DOG FACE, or Unicode scalar U+1F436):
let dogString = "Dog‼🐶"
UTF-8表現
for codeUnit in dogString.utf8 {
print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 226 128 188 240 159 144 182 "
UTF-16表現
for codeUnit in dogString.utf16 {
print("\(codeUnit) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 55357 56374 "
Unicodeスカラー表現
for scalar in dogString.unicodeScalars {
print("\(scalar.value) ", terminator: "")
}
print("")
// Prints "68 111 103 8252 128054 "
value
プロパティをクエリする代わりに、各UnicodeScalar
値を使用して、文字列補間などの新しい値を作成することもできます。
for scalar in dogString.unicodeScalars {
print("\(scalar) ")
}
// D
// o
// g
// ‼
// 🐶