Swift-arc-overview

提供:Dev Guides
移動先:案内検索

Swift-ARCの概要

メモリ管理機能とその使用は、Automatic Reference Counting(ARC)を通じてSwift 4言語で処理されます。 ARCは、システムリソースを初期化および初期化解除するために使用され、インスタンスが不要になったときに、クラスインスタンスによって使用されていたメモリスペースを解放します。 ARCは、コードインスタンス間の関係に関する情報を追跡して、メモリリソースを効果的に管理します。

ARCの機能

  • ARCは、init()によって新しいクラスインスタンスが作成されるたびに、情報を格納するためにメモリのチャンクを割り当てます。
  • インスタンスタイプとその値に関する情報はメモリに保存されます。
  • クラスインスタンスが不要になった場合、deinst()により、クラスインスタンスの保存と取得のためにメモリスペースが自動的に解放されます。
  • ARCは、現在参照しているクラスインスタンスのプロパティ、定数、および変数を追跡し、deinit()が未使用のインスタンスにのみ適用されるようにします。
  • ARCは、これらのクラスインスタンスプロパティ、定数、および変数への「強い参照」を維持して、クラスインスタンスが現在使用されている場合に割り当て解除を制限します。

ARCプログラム

class StudDetails {
   var stname: String!
   var mark: Int!

   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Swift 4
98

ARC強参照サイクルクラスインスタンス

class studmarks {
   let name: String
   var stud: student?

   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?

   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

Initializing: Swift 4
Initializing: ARC

ARCの弱参照と非所有参照

クラス型プロパティには、強参照サイクルを解決する2つの方法があります-

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

これらの参照は、あるインスタンスが参照サイクルで他のインスタンスを参照できるようにするために使用されます。 その後、インスタンスは、強い参照サイクルを気にする代わりに、すべてのインスタンスを参照する場合があります。 いくつかのインスタンスが「nil」値を返す可能性があることをユーザーが知っている場合、弱参照を使用してそれを示すことができます。 インスタンスがnilではなく何かを返す場合、所有されていない参照で宣言します。

弱い参照プログラム

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

ARC Is The Main Module
Sub Module with its topic number is 4

未所有の参照プログラム

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student

   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

ARC
Marks Obtained by the student is 98

クロージャの強力な参照サイクル

特定のインスタンスをキャプチャするためにクラスインスタンスプロパティとクロージャーの本体にクロージャーを割り当てると、強い参照サイクルが発生する可能性があります。 クロージャーへの強い参照は、「self.someProperty」または「self.someMethod()」によって定義されます。 強参照サイクルは、クロージャの参照タイプとして使用されます。

class HTMLElement {
   let samplename: String
   let text: String?

   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename)/>"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

<p>Welcome to Closure SRC</p>

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

クロージャーとインスタンスが相互に参照する場合、ユーザーはクロージャー内のキャプチャを非所有参照として定義できます。 その場合、ユーザーが同時にインスタンスの割り当てを解除することはできません。 インスタンスがいつか「nil」値を返すと、弱いインスタンスを持つクロージャが定義されます。

class HTMLElement {
   let module: String
   let text: String?

   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module)/>"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

プレイグラウンドを使用して上記のプログラムを実行すると、次の結果が得られます-

<Inside>ARC Weak References</Inside>
Inside the deinit()