自動参照カウント


Swift は、アプリのメモリ使用量を追跡し、管理するため 自動参照カウント (ARC) を使用します。ほとんどの場合、これはメモリ管理が Swift では "きちんと動く"ことを意味し、メモリ管理を自分自身で考える必要はありません。ARC は、クラスのインスタンスがもはや不要になったときにクラスインスタンスによって使用されるメモリを自動的に解放します。


しかし、いくつかの場合、ARC はメモリをあなたのために管理するために、コードの一部分の間の関係について、より多くの情報を必要とします。この章では、これらの状況を説明し、アプリのメモリをすべて管理するために、ARC を有効にする方法を示します。Swift での ARC の使用は、Objective-C で ARC を使用するための ARC への移行の公開ノート で説明したアプローチと非常によく似ています。


参照カウントは、クラスのインスタンスのみに適用されます。構造体と列挙型は、値型であり、参照型でないので、参照によって保存されたり渡されたりしません。


どのように ARC は働くか


クラスの新しいインスタンスを作成するたびに、ARC は、そのインスタンスに関する情報を格納するメモリの塊を割り当てます。このメモリは、そのインスタンスに関連付けられた格納されたプロパティの値と共に、インスタンスの型に関する情報を保持しています。


加えて、インスタンスがもはや不要になったときには、ARC は、メモリが代わりに他の目的に使用することができるように、そのインスタンスによって使用されていたメモリを解放します。これは、それらが不要になったときに、クラスインスタンスがメモリ内のスペースを占有しないことを保証します。


しかし、ARC は、まだ使用されているインスタンスの割り当てを解除しようとする場合、もはやそのインスタンスのプロパティにアクセスしたり、そのインスタンスのメソッドを呼び出すことはできないでしょう。確かに、インスタンスにアクセスしようとした場合には、アプリはクラッシュする可能性が非常に高いでしょう。


インスタンスがまだ必要な間、それらが消えてしまわない事を確かめるために、多くのプロパティ、定数、および変数が現在、各クラスインスタンスを参照する方法を、ARC は追跡します。ARC は、そのインスタンスへの有効な参照が少なくとも一つまだ存在している間は、インスタンスの割り当てを解除しません。


これを可能にするため、プロパティ、定数、または変数にクラスインスタンスを代入するときはいつでも、そのプロパティ、定数、または変数は、インスタンスへの 強い参照 を行います。参照は、そのインスタンスをしっかりと保持しているため "強い" 参照と呼ばれ、その強い参照が残っている間は、割り当てを解除することはできません。


実際の ARC


ここで、どのように自動参照カウントが働くかの例を挙げます。この例では、name と言う格納された定数プロパティを定義する Person と言う簡単なクラスで始まります:


  1. class Person {
  2.         let name: String
  3.         init(name: String) {
  4.                 self.name = name
  5.                 print("\(name) is being initialized")
  6.         }
  7.         deinit {
  8.                 print("\(name) is being deinitialized")
  9.         }
  10. }


Person クラスには、インスタンスの name プロパティを設定するイニシャライザがあり、その初期化が進行中であることを示すためにメッセージを出力します。Person クラスにはまた、クラスのインスタンスが割り当て解除されたときにメッセージを出力するデイニシャライザがあります。


次のコードスニペットは、後続のコードスニペットの新しい Person インスタンスへの複数の参照を設定するために使われる、Person? 型の3つの変数を定義しています。これらの変数は、optional 型 (Person ではなく Person?) なので、それらは自動的に nil の値で初期化され、現在は Person インスタンスを参照していません。


  1. var reference1: Person?
  2. var reference2: Person?
  3. var reference3: Person?


これで、新しい Person インスタンスを作成し、これらの3つの変数の一つにそれを代入できます。


  1. reference1 = Person(name: "John Appleseed")
  2. // prints "John Appleseed is being initialized"


"John Appleseed is initialized" というメッセージは、Person クラスのイニシャライザを呼び出した時点で出力されることに注意してください。これにより、初期化が行われたことが確認されます。


新しい Person インスタンスが reference1 変数に割り当てられているため、reference1 から新しい Person インスタンスへの強い参照ができます。少なくとも 1 つの強力な参照があるため、ARC はこの Person がメモリ内に保持され、割り当て解除されないことを確認します。


さらに2つの変数に同じ Person インスタンスを割り当てた場合、そのインスタンスへのさらに2つの強い参照が確立されます。


  1. reference2 = reference1
  2. reference3 = reference1


現在、この一つの Person インスタンスに、3つの 強い参照が存在しています。


そのうち2つの変数に nil を代入して (元の参照を含む)、これらの強い参照の2つを壊す場合、一つの強い参照が残り、Person インスタンスの割り当ては解除されません。


  1. reference1 = nil
  2. reference2 = nil


3番目で最後の強い参照が壊れるまで、Person インスタンスをもはや使用しなくなったことが明らかな時点でも ARC は Person インスタンスの割り当てを解除しません。


  1. reference3 = nil
  2. // prints "John Appleseed is being deinitialized"


クラスインスタンス間の強い循環参照


上記の例では、ARC は、作成した新しい Person インスタンスへの参照の数を追跡する事ができ、それがもはや不要になったときその Person インスタンスを割り当て解除できます。


しかし、クラスのインスタンスが 決して ゼロの強い参照を有する点には到達しないコードを書くことが可能です。2つのクラスインスタンスが、各インスタンスが他のインスタンスに生きたままでいようと、相互に強い参照を保持している場合はこれが発生することがあります。これは、強い循環参照 として知られています。


強い参照の代わりとして、弱い、または所有されていない参照としてクラス間の関係のいくつかを定義することにより、強い循環参照を解決できます。このプロセスは、クラスインスタンス間の強い循環参照の解決 で説明されています。しかし、強い循環参照を解決する方法を学ぶ前に、このような循環参照がなぜ起こったかを理解しておくと便利です。


ここに強い循環参照が偶然に作成されうる場合の例を示します。この例では、PersonApartment と言う2つのクラスを定義し、アパートのブロックとその住民をモデルにしています:


  1. class Person {
  2.         let name: String
  3.         init(name: String) { self.name = name }
  4.         var apartment: Apartment?
  5.         deinit { print("\(name) is being deinitialized") }
  6. }
  7. class Apartment {
  8.         let unit: String
  9.         init(unit: String) { self.unit = unit }
  10.         var tenant: Person?
  11.         deinit { print("Apartment \(unit) is being deinitialized") }
  12. }


すべての Person インスタンスには、String 型の name プロパティと、初期値は nil の、optional の apartment プロパティがあります。 person はアパートを常には持っていないため、apartment プロパティは、optional です。


同様に、すべての Apartment インスタンスには、String 型の unit プロパティと、初期値は nil の、optional の tenant プロパティがあります。アパートはテナントを常には持っていないため、tenant プロパティは optional です。


これらのクラスの両方とも、そのクラスのインスタンスがデイニシャライズされたという事を印刷するデイニシャライザも定義しています。これで期待通りに PersonApartment のインスタンスが割り当て解除されているかどうかを確認できます。


次のコードスニペットは、特定の Apartment と下記の Person インスタンスに設定されるだろう、johnunit4A と言う2つの optional 型の変数を定義しています。これらの変数はいずれも、optional であるおかげで、nil の初期値を持っています。


  1. var john: Person?
  2. var unit4A: Apartment?


これで、特定の Person インスタンスと Apartment インスタンスを作成し、johnunit4A 変数にこれらの新しいインスタンスを代入することができます。


  1. john = Person(name: "John Appleseed")
  2. unit4A = Apartment(unit: "4A")


強い参照がこれら2つのインスタンスを作成し、代入した後どのように見えるかここに示します。john 変数は今や、新しい Person インスタンスへの強い参照があり、unit4A 変数は、新しい Apartment インスタンスへの強い参照があります:



referenceCycle01_2x


person には apartment があり、apartment には tenant があり、一緒に2つのインスタンスをリンクできるようになりました。感嘆符 (!) は、それらのインスタンスのプロパティが設定できるように、johnunit4A の optional 変数内に格納されたインスタンスを開封し、アクセスできるように使用されていることに注意してください:


  1. john!.apartment = unit4A
  2. unit4A!.tenant = john


ここで、2つのインスタンスを一緒にリンクした後、強い参照がどう見えるかを示します。


referenceCycle02_2x


残念ながら、これらの2つのインスタンスをリンクすると、それらの間の強い循環参照を作成してしまいます。Person インスタンスは現在、Apartment インスタンスへの強い参照を持っており、Apartment インスタンスは Person インスタンスへの強い参照を持っています。そのため、johnunit4A 変数で保持された強い参照を壊しても、参照カウントはゼロに低下せず、インスタンスは、ARC によって割り当て解除されません。


  1. john = nil
  2. unit4A = nil


これら2つの変数を nil に設定しても、どちらのデイニシャライザも呼び出されないことに注意してください。強い循環参照は、割り当てが解除されることからいつまでも PersonApartment インスタンスを防ぎ、アプリ内のメモリリークを引き起こします。


ここで、johnunit4A 変数を nil に設定した後、強い参照がどう見えるかについて示します。



referenceCycle03_2x


Person インスタンスと Apartment インスタンスの間には強い参照が残っていて、壊すことができません。



クラスインスタンス間の強い循環参照の解決


Swift は、クラス型のプロパティを操作する際の強い循環参照を解決する為に2つの方法を提供しています:弱い参照と所有されていない参照です。


弱い参照と所有されていない参照は、その上に強い保持を維持すること なく、他のインスタンスを参照するための循環参照で1つのインスタンスを有効にします。インスタンスは、その後、強い循環参照を作ることなく、相互に参照することができます。


他のインスタンスの寿命が短い場合 (つまり、他のインスタンスを最初に割り当て解除できる場合) には、弱い参照を使用します。上に挙げた Apartment の例では、アパートの寿命中のある時点でテナントを持てないようにすることが適切であり、この場合、弱い参照が循環参照を壊す適切な方法です。これとは対照的に、他のインスタンスの寿命が同じか長い寿命である場合、所有されていない参照を使用します。



弱い参照


弱い参照 は、参照されるインスタンスの廃棄から ARC は停止しないので、それが参照するインスタンスに強い確保を維持しない参照です。この行動は、強い循環参照の一部になる事から参照を防止します。プロパティまたは変数宣言の前に weak キーワードを書いて、弱い参照である事を示して下さい。


弱い参照は、それが参照するインスタンスに強い保持をしないので、弱い参照がまだそれを参照している間に、そのインスタンスの割り当てを解除するのは可能です。そのため、割り当て解除されるインスタンスを参照している時、ARC は自動的に弱い参照を nil に設定します。そして、弱い参照は、それらの値が、実行時に nil に変更できるようにする必要があるため、それらは常に、定数ではなく、変数として optional の型を宣言をされています。


その参照は、その寿命中のある時点で値がない参照である可能性があるときはいつでも、循環参照を避けるために、弱い参照を使用してください。参照が 常に 値を持つ場合は、代わりに、所有されていない参照 で説明したように、所有されていない参照を使用して下さい。上記の例の Apartment では、その寿命のある時点でテナントがない場合がるるので、弱い参照は、この場合循環参照を壊すための適切な方法です。



注意: ARC が弱い参照を nil に設定するときには、プロパティ監視者は呼び出されません。


以下の例は、上記の PersonApartment の例と1つの重要な違いを除いて全く同じです。今度は、Apartment 型の tenant プロパティは弱い参照として宣言されています。


  1. class Person {
  2.         let name: String
  3.         init(name: String) { self.name = name }
  4.         var apartment: Apartment?
  5.         deinit { print("\(name) is being deinitialized") }
  6. }
  7. class Apartment {
  8.         let unit: String
  9.         init(unit: String) { self.unit = unit }
  10.         weak var tenant: Person?
  11.         deinit { print("Apartment \(unit) is being deinitialized") }
  12. }


2つの変数 (johnunit4A) からの強い参照と2つのインスタンスのリンクが以前のように作成されます。


  1. var john: Person?
  2. var unit4A: Apartment?
  3. john = Person(name: "John Appleseed")
  4. unit4A = Apartment(unit: "4A")
  5. john!.apartment = unit4A
  6. unit4A!.tenant = john


ここで、2つのインスタンスを一緒にリンクした時参照がどう見えるか示します:


weakReference01_2x


Person インスタンスには、まだ Apartment インスタンスへの強い参照がありますが、Apartment インスタンスには今や、Person インスタンスへの 弱い 参照しかありません。これは、john 変数を nil に設定して、保持する強い参照を壊すと、Person インスタンスへの強い参照がもはや存在しないことを意味します。



  1. john = nil
  2. // prints "John Appleseed is being deinitialized"


Person インスタンスへの強い参照がもはやないので、それは割り当て解除され、tenant プロパティは nil に設定されます。


weakReference02_2x


Apartment インスタンスへの唯一残った強い参照は unit4A 変数からです。その 強い参照を壊すと、 Apartment インスタンスへの強い参照はもはやありません。


  1. unit4A = nil
  2. // prints "Apartment 4A is being deinitialized"


Apartment インスタンスへの強い参照はもはやないので、それも割り当て解除されます:


weakReference03_2x


注意: ガベージコレクションを使用しているシステムでは、メモリ圧迫がガベージコレクションをトリガしたときにのみ強い参照を持たないオブジェクトは、割り当てが解除されないため、弱いポインタは時々単純なキャッシュ・メカニズムを実装するために使用されます。しかし、ARC では、そのような目的のためには弱い参照は適さないため、それらの最後の強い参照が削除されるやいなや値は割り当て解除されます。


所有されていない参照


弱い参照と同様に、インスタンス上でそれが参照する強力な保持を、所有されていない参照 は維持しません。しかし、弱い参照とは異なり、所有されていない参照は、他のインスタンスが同じ寿命か長い寿命を持っている時に使われます。プロパティまたは変数の宣言の前に unowned キーワードを書くことによって所有されていない参照を示します。


所有されていない参照は常に値を持つことが期待されます。その結果、ARC は所有されていない参照を nil に設定することは決してなく、つまり、所有されていない参照は optional でない型を使用して定義されます。


注意: 参照が 常に 割り当て解除されていないインスタンスを参照していると確信している場合にのみ、所有されていない参照を使用してください。

そのインスタンスの割り当てが解除された後に、所有されていない参照の値にアクセスしようとすると、実行時エラーが発生します。


以下の例では、2つのクラス、CustomerCreditCard を定義しており、銀行の顧客とその顧客用のクレジットカードをモデルにしています。これら2つのクラスはそれぞれ、プロパティとして、他のクラスのインスタンスを格納します。この関係は、強い循環参照を作成する可能性があります。


CustomerCreditCard の関係は、上記の弱い参照の例に見られる ApartmentPerson の関係とは少し異なります。このデータモデルでは、顧客は、クレ ジットカードを持っていてもいなくてもよいですが、クレジットカードは、常に 顧客に関連付けられます。CreditCard のインスタンスは、それが参照する Customer よりも長生きすることは決してありません。これを表現するために、Customer クラスには、optional の card プロパティがありますが、CreditCard クラスには (optional でない) customer プロパティーがあります。


さらに、新しい CreditCard インスタンスは、カスタムの CreditCard イニシャライザに number 値と customer インスタンスを渡すことで のみ 作成することができます。これは、CreditCard インスタンスが作成されるとき、CreditCard インスタンスは常に、それに関連付けられた customer インスタンスを持っていることを確実にします。


クレジットカードには、常に顧客があるので、強い循環参照を避けるために、その customer プロパティを、所有されていない参照として定義します。


  1. class Customer {
  2.         let name: String
  3.         var card: CreditCard?
  4.         init(name: String) {
  5.                 self.name = name
  6.         }
  7.         deinit { print("\(name) is being deinitialized") }
  8. }
  9. class CreditCard {
  10.         let number: UInt64
  11.         unowned let customer: Customer
  12.         init(number: UInt64, customer: Customer) {
  13.                 self.number = number
  14.                 self.customer = customer
  15.         }
  16.         deinit { print("Card #\(number) is being deinitialized") }
  17. }


注意: CreditCard クラスの number プロパティは Int ではなく UInt64 型として定義されていますが、number プロパティの容量が 32 ビットと 64 ビットの両方のシステムで 16 桁のカードの番号を格納するのに十分な大きさであることを保証するためです。


次のコードスニペットは、john と言う optional の Customer 変数を定義し、特定の customer への参照を格納するために使用されます。この変数は optional であるおかげで、nil の初期値を持っています:


var john: Customer?



これで、Customer インスタンスを作成し、初期化し、その customer (顧客) の card プロパティとして新しい CreditCard インスタンスを割り当てて使用できるようになりました。


  1. john = Customer(name: "John Appleseed")
  2. john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)


ここで、2つのインスタンスをリンクした今、参照がどのように見えるかを示します。



unownedReference01_2x


Customer インスタンスには今や、CreditCard インスタンスへの強い参照があり、CreditCard インスタンスには Customer インスタンスへの所有されていない参照があります。


所有されていない customer の参照のため、john 変数で保持される強い参照を壊すと、Customer インスタンスへの強い参照はもはやありません。



unownedReference02_2x


Customer インスタンスへの強い参照がもはやないので、それは割り当て解除されます。これが起こった後、 CreditCard インスタンスへの強い参照がもはやなくなり、それもまた割り当て解除されます:


  1. john = nil
  2. // prints "John Appleseed is being deinitialized"
  3. // prints "Card #1234567890123456 is being deinitialized"


上記に示した最後のコードスニペットは、Customer インスタンスと CreditCard インスタンスのためのデイニシャライザが、john 変数が nil に設定された後 "deinitialized" のメッセージを両方とも印刷する事を示しています。



注意: 上記の例では、安全な 所有されていない参照を使用する方法を示しています。Swift はまた、実行時の安全性チェックを無効にする必要がある場合 (たとえば、パフォーマンス上の理由など) に、安全でない 所有されていない参照を提供します。すべての安全でない操作と同様に、あなたにはそのコードの安全性をチェックする責任があります。

unowned(unsafe) を書いて、安全でない所有されていない参照を指定して下さい。参照するインスタンスが割り当て解除された後で、安全でない所有されていない参照にアクセスしようとすると、プログラムはそのインスタンスが使用されていたメモリ位置にアクセスしようとし、それは安全でない操作です。


所有されていない参照と暗黙に開封された Optional のプロパティ


上記に示した弱い参照と所有されていない参照は、強い循環参照を断ち切るのに必要である、より一般的な2つのシナリオをカバーしています。


PersonApartment の例では、両方とも nil であることが許されている2つのプロパティの場合を示し、強い循環参照を引き起こす潜在性があります。このシナリオは、弱い参照で最も良く解決されます。


CustomerCreditCard の例では、nil であることが許されている1つのプロパティと、強い循環参照参照を引き起こす可能性のある、nil であるることはできない別のプロパティの場合を示しています。このシナリオは、所有されていない参照で最も良く解決されます。


しかし、両方の プロパティが常に値を持つ第三のシナリオがあり、どちらのプロパティとも、一度初期化が完了すると nil には決してなりえません。このシナリオでは、他のクラス上の暗黙的に開封された optional のプロパティと1つのクラスの所有されていないプロパティを組み合わせることが有効です。


これは、初期化が一度完了すると、まだ循環参照を回避しながら、両方のプロパティは、(optional の開封なしで) 直接アクセスすることができます。このセクションでは、そのような関係をどのように設定するかを示しています。


以下の例は、プロパティとして、他のクラスのインスタンスをそれぞれ格納する2つのクラス、CountryCity を定義しています。このデータモデルでは、すべての country は常に、首都を持っている必要があり、すべての都市は常に country に属していなければなりません。これを表現するために、Country クラスには capitalCity プロパティがあり、City クラスには country プロパティがあります。


  1. class Country {
  2.         let name: String
  3.         var capitalCity: City!
  4.         init(name: String, capitalName: String) {
  5.                 self.name = name
  6.                 self.capitalCity = City(name: capitalName, country: self)
  7.         }
  8. }
  9. class City {
  10.         let name: String
  11.         unowned let country: Country
  12.         init(name: String, country: Country) {
  13.                 self.name = name
  14.                 self.country = country
  15.         }
  16. }


2つのクラス間の相互依存性を設定する為に、City のイニシャライザは、Country のインスタンスを取り、このインスタンスを country プロパティに保存します。


City のイニシャライザは、Country のイニシャライザ内から呼び出されます。しかし、Country のイニシャライザは、二相の初期化 で説明したように、新しい Country インスタンスが完全に初期化されるまで、City のイニシャライザに self を渡すことはできません。


この要件に対処するには、その型注釈の最後に感嘆符を付けて (City!)、暗黙的に開封された optional のプロパティとして CountrycapitalCity プロパティを宣言します。これは capitalCity プロパティは、他の optional のように nil のデフォルト値を持っていますが、暗黙的に開封された Optional で説明したように、その値を開封する必要なくアクセスできることを意味します。


capitalCity がデフォルトで nil 値を持っているので、新しい Country インスタンスは、Country インスタンスが、そのイニシャライザ内の name プロパティを設定するやいなや完全に初期化されたとみなされます。これは Country イニシャライザが参照し始める事ができ、name プロパティが設定されるやいなや、暗黙的な self プロパティを渡せることを意味します。Country イニシャライザは、そのため Country イニシャライザが独自の capitalCity プロパティを設定している時 City イニシャライザのパラメータの一つとして self を渡す事ができます。


このすべては、強い循環参照を作成せずに、一つの文で CountryCity インスタンスを作成でき、また capitalCity プロパティがその optional 値を開封するために感嘆符を使用することなしに、直接アクセスできることを意味します。


  1. var country = Country(name: "Canada", capitalName: "Ottawa")
  2. print("\(country.name)'s capital city is called \(country.capitalCity.name)")
  3. // prints "Canada's capital city is called Ottawa"


上記の例では、暗黙的に開封された optional の使用は、二相クラスのイニシャライザの要件がすべて満たされていることを意味します。初期化が一度完了すると capitalCity プロパティは使用でき、optional でない値と同じようにアクセスでき、まだ強い循環参照を回避できます。


クロージャの強い循環参照


2つのクラスインスタンスのプロパティがお互いへの強い参照を保持する際に強い循環参照を作成する事を上で示しました。また、これらの強い循環参照を壊すのに、弱い参照と所有されていない参照を使う方法を説明しました。


クラスインスタンスのプロパティにクロージャを割り当てた場合にも、強い循環参照が発生することがあり、そしてそのクロージャの本体は、インスタンスをキャプチャします。このキャプチャはクロージャの本体が self.someProperty のようにインスタンスのプロパティにアクセスするために発生し、またはクロージャが self.someMethod() のようにインスタンス上のメソッドを呼び出すと発生します。いずれの場合でも、これらのアクセスは、強い循環参照を作り、クロージャに self を "キャプチャ"する事を引き起こします。


クロージャは、クラスのように、参照型 であるため、この強い循環参照が発生します。プロパティにクロージャを割り当てると、そのクロージャに 参照 を割り当てています。本質的に、それは2つの強い参照が生きていてお互いを維持している、上記と同様の問題があります。しかし、むしろ2つのクラスインスタンスよりも、ここでは、生きてお互いを維持しているクラスインスタンスとクロージャです。


Swift は クロージャキャプチャリスト として知られている、この問題へのエレガントな解決法を提供します。しかし、クロージャキャプチャリストで強い循環参照を壊す方法を学ぶ前に、このような循環がどのように発生するかを理解しておくと便利です。


以下の例では、self を参照するクロージャを使用しているときに、強い循環参照を作成してしまう方法を示しています。この例では、HTMLElement と言うクラスを定義し、HTML の書類内の個々の要素の単純なモデルとして提供しています。


  1. class HTMLElement {
  2.         let name: String
  3.         let text: String?
  4.         lazy var asHTML: () -> String = {
  5.                 if let text = self.text {
  6.                 return "<\(self.name)>\(text)</\(self.name)>"
  7.                 } else {
  8.                 return "<\(self.name) />"
  9.                 }
  10.         }
  11.         init(name: String, text: String? = nil) {
  12.                 self.name = name
  13.                 self.text = text
  14.         }
  15.         deinit {
  16.                 print("\(name) is being deinitialized")
  17.         }
  18. }


HTMLElement クラスは、見出し要素の "h1"、段落要素の "p"、または改行要素の "br" としてのように、要素の名前を示す name プロパティを定義しています。HTMLElement はまた、その HTML 要素内にレンダリングされるテキストを表す文字列に設定できる optional の text プロパティも定義しています。


これら二つの単純なプロパティに加えて、HTMLElement クラスは asHTML と言う遅延した(lazy) プロパティを定義しています。このプロパティは、HTML 文字列の断片に nametext を組み合わせるクロージャを参照しています。asHTML プロパティは () -> String 型であり、または "パラメータを取らない、String 値を返す関数" です。


デフォルトでは、asHTML プロパティは、HTML タグの文字列表現を返すクロージャが割り当てられています。それが存在する場合、または全くテキストコンテンツの text が存在しない場合、このタグは、optional の text 値を含んでいます。段落要素については、クロージャは text プロパティが "some text"nil に等しいかどうかに応じて、"<p>some text</p>" または "<p />" を返します。


asHTML プロパティは、多少インスタンスメソッドのような名前を付けられ使用されています。しかし、asHTML は、インスタンスメソッドと言うよりクロージャプロパティであるため、特定の HTML 要素のための HTML レンダリングを変更したい場合は、カスタムのクロージャで asHTML プロパティのデフォルト値を置き換えることができます。


例えば、asHTML プロパティは、text プロパティがnil の場合、空の HTML タグを返す事からの表現を防止するために、デフォルトをいくつかのテキストにするクロージャーに設定することができます。


  1. let heading = HTMLElement(name: "h1")
  2. let defaultText = "some default text"
  3. heading.asHTML = {
  4.         return "<\(heading.name)>\(heading.text ?? defaultText)<\(heading.name)>"
  5. }
  6. print(heading.asHTML())
  7. // Prints "<h1>some default text</h1>"


注意: 要素が、実際にいくつかの HTML 出力対象の文字列値としてレンダリングされる必要がある場合にのみ必要とされるため asHTML プロパティは、遅延した(lazy) プロパティとして宣言されています。asHTML は遅延したプロパティであるという事実は、遅延したプロパティの初期化が完了し、self が存在することが知られた後までアクセスできなくなるので、デフォルトのクロージャ内で self を参照できることを意味します。


HTMLElement クラスは、新しい要素を初期化するために、name 引数と(必要に応じて) text 引数を取る、単一のイニシャライザを提供します。クラスはまた、HTMLElement インスタンスが割り当て解除されたときにメッセージを表示して印刷するデイニシャライザも定義しています。


新しいインスタンスを作成し、印刷する HTMLElement クラスを使用する方法をここに示します。


  1. var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
  2. print(paragraph!.asHTML())
  3. // prints "<p>hello, world</p>"


注意: 上記の paragraph 変数は optionalHTMLElement として定義され、そのため強い循環参照の存在を実証するために、下記では nil に設定できます。


残念ながら、HTMLElement クラスは上に書いたように、HTMLElement インスタンスとそのデフォルトの asHTML 値に使用されたクロージャの間に強い循環参照を作成します。ここで、循環参照がどのように見えるか示します:



closureReferenceCycle01_2x


インスタンスの asHTML プロパティは、そのクロージャへの強い参照を保持します。しかし、クロージャがその本体(self.nameself.text を参照する方法として) 内に self を参照するので、クロージャは、self を キャプチャ しているので、それは HTMLElement インスタンスへ戻る強い参照を保持していることを意味します。強い循環参照は2つの間に作成されます。(クロージャの中の値をキャプチャする方法の詳細については、値のキャプチャ を参照してください。)



注意: クロージャが self に複数回参照しても、HTMLElement インスタンスへの1つの強い参照をキャプチャするだけです。


paragraph 変数を nil に設定し、HTMLElement インスタンスへの強い参照を壊す場合、HTMLElement インスタンスもそのクロージャのいずれも、強い循環参照のため、割り当て解除されません。


paragraph = nil



HTMLElement デイニシャライザ内のメッセージは印刷されず、それは HTMLElement インスタンスが割り当て解除されないことを示しているのに注意してください。



クロージャの強い循環参照の解決


クロージャの定義の一部として キャプチャリスト を定義することで、クロージャとクラスインスタンス間の強い循環参照を解決できます。キャプチャリストは、クロージャの本体内の1つ以上の参照型をキャプチャする際に使用する規則を定義します。2つのクラスインスタンス間の強い循環参照と同じように、強い参照ではなく、各々キャプチャされた参照を、弱い参照または所有されていない参照として宣言して下さい。弱い参照または所有されていない参照の適切な選択は、コードの異なる部分の間の関係に依存します。



注意: Swift ではクロージャ内で self のメンバーを参照する時はいつでも self.someProperty または self.someMethod() (somePropertysomeMethod()ではなく) と記述する必要があります。これは、間違って self をキャプチャすることがあるのを思い出すのを助けます。


キャプチャリストの定義


キャプチャリストの各項目は、クラスインスタンスへの参照と、weak または unowned キーワードとペアリングして(self のように)、またある値で初期化された変数 (delegate = self.delegate! のように) とペアリングします。これらのペアリングは、カンマで区切って角括弧のペア内に記述されます。


クロージャのパラメータリストの前にキャプチャリストを配置し、戻り値の型が提供されている場合はそれを書きます:


  1. lazy var someClosure: (Int, String) -> String = {
  2.         [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
  3.         // closure body goes here
  4. }


パラメータリストや戻り値の型が文脈から推測することができるのでクロージャがそれらを指定しない場合、クロージャの最初にキャプチャリストを配置し、in キーワードを続けます:


  1. lazy var someClosure: () -> String = {
  2.         [unowned self, weak delegate = self.delegate!] in
  3.         // closure body goes here
  4. }


弱い参照と所有されていない参照


クロージャーとそれがキャプチャするインスタンスは常にお互いに参照し、常に同時に割り当て解除されるときに、クロージャーで所有されていない参照としてキャプチャを定義します。


逆に、弱い参照としてキャプチャを定義し、キャプチャされた参照は将来のある時点で nil になりえます。弱い参照は常に optional 型であり、それらが参照するインスタンスが割り当て解除されると自動的に nil になります。これでクロージャの本体内にそれらが存在する事を確認できます。



注意: キャプチャされた参照が nil になることが決してなければ、弱い参照としてではなく所有されていない参照として、常にキャプチャされます。


所有されていない参照は、以前示した HTMLElement の例では強い循環参照を解決するために使用する適切なキャプチャメソッドです。ここで、循環参照を回避するため HTMLElement クラスをどう書くか、方法を示します。


  1. class HTMLElement {
  2.         let name: String
  3.         let text: String?
  4.         lazy var asHTML: () -> String = {
  5.                 [unowned self] in
  6.                 if let text = self.text {
  7.                         return "<\(self.name)>\(text)</\(self.name)>"
  8.                 } else {
  9.                         return "<\(self.name) />"
  10.                 }
  11.         }
  12.         init(name: String, text: String? = nil) {
  13.                 self.name = name
  14.                 self.text = text
  15.         }
  16.         deinit {
  17.                 print("\(name) is being deinitialized")
  18.         }
  19. }


この HTMLElement の実装は、asHTML クロージャ内のキャプチャリストの追加を別にすれば、以前の実装と完全に同一です。この場合、キャプチャリストは、"強い参照ではなく、所有されていない参照として self をキャプチャする" を意味する、[unowned self] です。


以前のように HTMLElement インスタンスを作成し、印刷できます。


  1. var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
  2. print(paragraph!.asHTML())
  3. // prints "<p>hello, world</p>"


参照がキャプチャリストの所定の位置でどのように見えるかをここに示します:



closureReferenceCycle02_2x


今度は、クロージャによる self のキャプチャは所有されていない参照であり、それがキャプチャした HTMLElement インスタンス上では強い保持を維持しません。paragraph 変数からの強い参照を nil に設定した場合は、以下の例で、そのデイニシャライザのメッセージの印刷から分かるように、HTMLElement インスタンスは、割り当てが解除されます。


  1. paragraph = nil
  2. // prints "p is being deinitialized"


キャプチャリストの詳細については、キャプチャ・リスト を参照してください。





前:汎用 次:メモリの安全性
目次
Xcode 9 の新機能

Swift:はじめに
Swift と Cocoa と Objective-C
Swift Blog より

  • ようこそ Swift へ(Part I)
  • Swift について
  • バージョン互換性
  • Swift のツアー
  • 単純な値
    制御フロー
    関数とクロージャ
    オブジェクトとクラス
    列挙型と構造体
    プロトコルと拡張機能
    エラー処理
    汎用(ジェネリック)
  • Swift 言語のガイド(Part II)
  • Swift の基本
  • 定数と変数
  • 定数と変数の宣言
    型注釈
    定数と変数の命名
    定数と変数の印刷
    コメント
    セミコロン
  • 整数
  • 整数の境界
    Int
    UInt
    浮動小数点数
    安全な型と型推論
    数値リテラル
  • 数値型変換
  • 整数変換
    整数と浮動小数点間の変換
    型エイリアス
    ブール型
    タプル
  • Optional
  • nil
    if 文と強制開封
    Optional の結合
    暗黙に開封された Optionals
    エラー処理
  • アサーション(断言)と前提条件
  • アサーションを使用したデバッグ
    前提条件の実施
  • 基本演算子
  • 専門用語
    代入演算子
  • 算術演算子
  • 剰余演算子
    単項マイナス演算子
    単項プラス演算子
    複合代入演算子
    比較演算子
    三項条件演算子
    Nil 合体演算子
  • 範囲演算子
  • 閉鎖範囲演算子
    半開放範囲演算子
    片方の範囲
  • 論理演算子
  • 論理 NOT 演算子
    論理 AND 演算子
    論理 OR 演算子
    論理演算子の組み合わせ
    明示的な括弧
  • 文字列と文字
  • 文字列リテラル
    複数行の文字列リテラル
    文字列リテラル内の特殊文字
    空の文字列の初期化
    文字列の可変性
    文字列は値の型
    文字を使った作業
    文字列と文字を連結
    文字列補間
  • ユニコード(Unicode)
  • Unicode スカラー
    文字列リテラルの中の特別の文字
    拡張書記クラスタ
    文字を数える
  • 文字列のアクセスと変更
  • 文字列のインデックス
    部分文字列
    挿入と削除
  • 文字列の比較
  • 文字列と文字の等価性
    接頭辞と接尾辞の等価性
  • 文字列の Unicode 表現
  • UTF-8 の表現
    UTF-16 表現
    Unicode のスカラー表現
  • コレクション型
  • コレクションの可変性
  • 配列
  • 配列型省略構文
    空の配列の作成
    デフォルト値を持つ配列の作成
    2つの配列を共にして一つの配列に
    配列リテラルでの配列の作成
    配列へのアクセスと変更
    配列の繰り返し処理
  • セット
  • セット型のハッシュ値
    セット型の構文
    空のセットの作成と初期化
    配列リテラルでセットの作成
    セットへのアクセスと変更
    セットを反復処理
  • セット操作の実行
  • 基本的なセットの操作
    セットの身分と等価性
  • Dictionary
  • Dictionary 型の省略型構文
    空の Dictionary を作成
    Dictionary リテラルで Dictionary の作成
    Dictionary のアクセスと変更
    Dictionary を繰り返し処理
  • フロー制御
  • For-In ループ
  • While ループ
  • While
    Repeat-While
  • 条件文
  • if 文
  • Switch
  • 暗黙の Fallthrough なし
    範囲の一致
    タプル(Tuples)
    値の結合
    Where
    複合した case
  • 制御転送文
  • Continue
  • Break
  • ループ文内の Break
    Switch 文内の Break
    Fallthrough
    ラベル付きの文
    早期終了
    API 利用可能性の確認
  • 関数
  • 関数の定義と呼び出し
  • 関数のパラメータと戻り値
  • パラメータなしの関数
    複数パラメータの関数
    戻り値なしの関数
    複数の戻り値を持つ関数
    optional のタプル型の戻り値
  • 関数引数のラベルとパラメータ名
  • 引数のラベルの指定
    引数ラベルの省略
    デフォルトのパラメータ値
    可変個引数のパラメータ
    In-Out パラメータ
  • 関数型
  • 関数型の使用
    パラメータ型としての関数型
    戻り値の型としての関数型
    入れ子になった関数
  • クロージャ
  • クロージャ式
  • ソートするメソッド
    クロージャ式の構文
    文脈から型を推論
    単一式クロージャからの暗黙的戻り値
    引数名の省略
    演算子メソッド
    後続クロージャ
    値のキャプチャ
    クロージャは参照型
    クロージャのエスケープ
    オートクロージャ
  • 列挙型
  • 列挙型の構文
    switch 文で列挙型の値の一致
    関連する値
  • 生の値
  • 暗黙に割り当てられた生の値
    生の値からの初期化
    再帰的な列挙型
  • クラスと構造体
  • クラスと構造体を比較
  • 定義の構文
    クラスと構造体のインスタンス
    プロパティにアクセス
    構造体型のためのメンバー化イニシャライザ
    構造体と列挙型は値型
  • クラスは参照型
  • ID 演算子
    ポインタ
    クラスと構造体の間の選択
    文字列、配列、辞書の代入とコピーの動作
  • プロパティ
  • 格納されたプロパティ
  • 定数構造体インスタンスの格納されたプロパティ
    遅延した格納されたプロパティ
    格納されたプロパティとインスタンス変数
  • 計算されたプロパティ
  • セッタ宣言の省略形
    読み取り専用の計算されたプロパティ
    プロパティ監視者
    グローバルとローカル変数
  • 型プロパティ
  • 型プロパティの構文
    型プロパティの照会と設定
  • メソッド
  • インスタンスメソッド
  • self プロパティ
    インスタンスメソッド内から値の型を変更
    変異メソッド内で self に代入
    型メソッド
  • サブスクリプト
  • サブスクリプトの構文
    サブスクリプトの使用法
    サブスクリプトのオプション
  • 継承
  • 基本クラスの定義
    サブクラス化
  • オーバーライド(上書き)
  • スーパークラスメソッド、プロパティ、サブスクリプトへのアクセス
    オーバーライドするメソッド
  • オーバーライドするプロパティ
  • プロパティのゲッタとセッタのオーバーライド
    プロパティ監視者のオーバーライド
    オーバーライドの防止
  • 初期化
  • 格納されたプロパティの初期値を設定
  • イニシャライザ
    デフォルトのプロパティ値
  • 初期化のカスタマイズ
  • 初期化パラメータ
    パラメータ名と引数ラベル
    引数ラベルのないイニシャライザのパラメータ
    Optional のプロパティ型
    初期化中に定数プロパティへの代入
  • デフォルトのイニシャライザ
  • 構造体型のためのメンバ化イニシャライザ
    値型のイニシャライザデリゲート
  • クラスの継承と初期化
  • 指定イニシャライザとコンビニエンスイニシャライザ
    指定とコンビニエンスイニシャライザの構文
    クラス型のイニシャライザデリゲート
    二相の初期化
    イニシャライザ継承とオーバーライド
    自動イニシャライザの継承
    実際の指定とコンビニエンスイニシャライザ
  • 失敗可能イニシャライザ
  • 生の値を持つ列挙型のための失敗可能イニシャライザ
    初期化失敗の伝播
    失敗可能イニシャライザのオーバーライド
    init! の失敗可能イニシャライザ
    必須イニシャライザ
    クロージャや関数でのデフォルトのプロパティ値設定
  • デイニシャライザ
  • デイニシャライザはどのように働くか
    作動中のデイニシャライザ
  • Optional の連鎖
  • 強制開封の代替としての Optional の連鎖
    Optional の連鎖のモデルクラスの定義
    Optional の連鎖を使用したプロパティへのアクセス
    Optional の連鎖を通じてメソッドを呼び出す
  • Optional の連鎖を通じてサブスクリプトへのアクセス
  • Optional 型のサブスクリプトにアクセス
    連鎖の複数レベルのリンク
    optional の戻り値を持つメソッドでの連鎖
  • エラー処理
  • エラーの表現と Throw
    エラーの処理
    throw 関数を使用したエラーの伝播
    Do-Catch を使用したエラー処理
    エラー をOptional の値に変換
    エラー伝播を無効に
    クリーンアップアクションの指定
  • 型キャスト
  • 型キャストのためのクラス階層の定義
    型のチェック
    ダウンキャスト
  • Any と AnyObjecgt 用の型キャスティング
  • ネストした型
  • 実際のネストした型
    ネストした型への参照
  • 拡張機能
  • 拡張機能の構文
    計算されたプロパティ
    イニシャライザ
  • メソッド
  • 変異インスタンスメソッド
    サブスクリプト
    ネストした型
  • プロトコル
  • プロトコルの構文
    プロパティの要件
    メソッドの要件
    変異メソッドの要件
  • イニシャライザの要件
  • プロトコルイニシャライザ要件のクラス実装
    失敗可能イニシャライザの要件
    型としてのプロトコル
    デリゲート
  • 拡張機能を持つプロトコル準拠の追加
  • 拡張機能を持つプロトコルの採用を宣言
    プロトコル型のコレクション
    プロトコルの継承
    クラス専用プロトコル
    プロトコルの構成
    プロトコル準拠の確認
    Optional のプロトコル要件
  • プロトコル拡張機能
  • デフォルトの実装の提供
    プロトコル拡張機能に制約を追加
  • ジェネリック(汎用)
  • 汎用が解決する問題
    汎用関数
    型パラメータ
    型パラメータの命名
    汎用の型
    汎用型の拡張
  • 型の制約
  • 型制約の構文
    実際の型の制約
  • 関連型
  • 実際の関連型
    既存の型を拡張して関連型を指定
    型注釈を使用して関連型を制約
    汎用の Where 句
    汎用の Where 句を含む拡張機能
    関連する型と汎用の Where 句
    汎用のサブスクリプト
  • 自動参照カウント
  • どのように ARC は働くか
    実際の ARC
    クラスインスタンス間の強い循環参照
  • クラスインスタンス間の強い循環参照の解決
  • 弱い参照
    所有されていない参照
    所有されていない参照と暗黙に開封された Optional のプロパティ
    クロージャの strong な循環参照
  • クロージャの strong な循環参照の解決
  • キャプチャリストの定義
    弱い参照と所有されていない参照
  • メモリの安全性
  • メモリへのアクセス競合の理解
    メモリアクセスの特徴
    In-Out パラメータへのアクセスの競合
    メソッド内の Self へのアクセスの競合
    プロパティへのアクセスの競合
  • アクセス制御
  • モジュールとソースファイル
  • アクセスレベル
  • アクセスレベルの全体的指針
    デフォルトのアクセスレベル
    ターゲット一つのアプリのアクセスレベル
    フレームワークのアクセスレベル
    ユニットテストのターゲット用のアクセスレベル
    アクセス制御の構文
  • カスタム型
  • タプル型
    関数型
  • 列挙型
  • 生の値と関連する値
    ネストした型
    サブクラス化
  • 定数、変数、プロパティ、およびサブスクリプト
  • ゲッタとセッタ
  • イニシャライザ
  • デフォルトのイニシャライザ
    構造体型用のデフォルトメンバ化イニシャライザ
  • プロトコル
  • プロトコルの継承
    プロトコルの準拠
  • 拡張機能
  • 拡張機能の private メンバ
    汎用
    型エイリアス
  • 高度な演算子
  • ビット単位演算子
  • ビット単位の NOT 演算子
    ビット単位の AND 演算子
    ビット単位の OR 演算子
    ビット単位の XOR 演算子
  • ビット単位の左と右シフト演算子
  • 符号なし整数のシフト動作
    符号付き整数のシフト動作
  • オーバーフロー演算子
  • 値オーバーフロー
    優先順位と結合性
  • 演算子メソッド
  • 接頭辞と接尾辞演算子
    複合代入演算子
    等価演算子
  • カスタム演算子
  • カスタム挿入辞演算子の優先順位
  • 言語のガイド(Part III)
  • 言語リファレンスについて
  • 文法の読み方
  • 語彙の構造
  • 空白とコメント
    識別子
    キーワードと句読点
  • リテラル
  • 整数リテラル
    浮動小数点リテラル
    文字列のリテラル
    演算子

  • 型注釈
    型識別子
    タプル型
    関数型
    エスケープしないクロージャの制限事項
    配列型
    辞書型
    Optional の型
    暗黙に開封された Optional の型
    プロトコル構成の型
    メタタイプ型
    型の継承句
    型の推測

  • 接頭辞式
    Try 演算子
  • 二項式
  • 代入演算子
    三項条件演算子
    型キャスト演算子
  • 一次式
  • リテラル式
    Self 式
    スーパークラス式
  • クロージャ式
  • キャプチャ・リスト
    暗黙のメンバ式
    括弧で囲まれた式
    タプル式
    ワイルドカード式
    キーパス式
    セレクタ式
    キーパス文字列式
  • 接尾辞の式
  • 関数呼び出し式
    イニシャライザ式
    明示的なメンバ式
    接尾辞の Self 式
    サブスクリプト 式
    強制値の式
    Optional の連鎖式

  • ループ文
  • For-In 文
    While 文
    Repeat-While 文
  • 分岐文
  • if 文
    Guard 文
  • switch 文
  • switch 文は、網羅的である必要あり
    実行が暗黙的に case を Fall Through しない
    ラベル付き文
  • 制御転送文
  • break 文
    continue 文
    fallthrough 文
    return 文
    throw 文
    defer 文
    do 文
  • コンパイラ制御文
  • 条件コンパイルブロック
    行制御文
    利用可能条件
  • 宣言
  • トップレベルのコード
    コードブロック
    Import 宣言
    ­定数の宣言
  • 変数の宣言
  • 格納された変数と格納された変数のプロパティ
    計算された変数と計算されたプロパティ
    格納された変数監視者とプロパティの監視者
    型変数プロパティ
    型エイリアス宣言
  • 関数の宣言
  • パラメータ名
    In-Out パラメータ
    パラメータの特殊な種類
    メソッドの特殊な種類
    Throw する関数とメソッド
    Rethrow する関数とメソッド
    決して返さない関数
  • 列挙型の宣言
  • 任意の型の case を列挙
  • 間接による列挙
    生の値型の case を列挙
    列挙型 case へのアクセス
    構造体の宣言
    クラスの宣言
  • プロトコルの宣言
  • プロトコル・プロパティ宣言
    プロトコル・メソッド宣言
    プロトコル・イニシャライザ宣言
    プロトコル・サブスクリプト宣言
    プロトコルに関連した型の宣言
  • イニシャライザ宣言
  • 失敗可能イニシャライザ
    デイニシャライザ宣言
    拡張機能の宣言
    サブスクリプト宣言
    演算子の宣言
    優先順位グループ宣言
  • 宣言修飾子
  • アクセス制御レベル
  • 属性
  • 宣言の属性
  • インターフェイスビルダーで使われる宣言属性
    型の属性
  • パターン
  • ワイルドカードパターン
    識別子パターン
    値結合パターン
    タプルパターン
    列挙型 case パターン
    Optional のパターン
    型キャストパターン
    式のパターン
  • 汎用パラメータと引数
  • 汎用パラメータ句
  • 汎用の where 句
    汎用引数句
  • 文法のまとめ
  • 語彙の構造



    宣言
    属性
    パターン
    汎用パラメータと引数
  • マニュアルの変更履歴
  • 変更履歴












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)