Swift-ARC 개요

메모리 관리 기능과 그 사용은 자동 참조 계수 (ARC)를 통해 Swift 4 언어로 처리됩니다. ARC는 시스템 리소스를 초기화하고 초기화하는 데 사용되어 인스턴스가 더 이상 필요하지 않을 때 클래스 인스턴스에서 사용하는 메모리 공간을 해제합니다. ARC는 메모리 리소스를 효과적으로 관리하기 위해 코드 인스턴스 간의 관계에 대한 정보를 추적합니다.

ARC의 기능

  • ARC는 init ()에 의해 새 클래스 인스턴스가 생성 될 때마다 정보를 저장하기 위해 메모리 청크를 할당합니다.

  • 인스턴스 유형 및 해당 값에 대한 정보는 메모리에 저장됩니다.

  • 클래스 인스턴스가 더 이상 필요하지 않으면 추가 클래스 인스턴스 저장 및 검색을 위해 deinit ()에 의해 메모리 공간을 자동으로 해제합니다.

  • 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)

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Swift 4
98

ARC Strong Reference Cycles 클래스 인스턴스

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

Initializing: Swift 4
Initializing: ARC

ARC 약하고 소유되지 않은 참조

클래스 유형 속성에는 강력한 참조주기를 해결하는 두 가지 방법이 있습니다.

  • 약한 참조
  • 소유되지 않은 참조

이러한 참조는 한 인스턴스가 참조주기의 다른 인스턴스를 참조 할 수 있도록하는 데 사용됩니다. 그런 다음 인스턴스는 강력한 참조주기를 고려하는 대신 각 인스턴스를 참조 할 수 있습니다. 사용자가 일부 인스턴스가 '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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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())

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

<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

Playground를 사용하여 위의 프로그램을 실행하면 다음과 같은 결과를 얻습니다.

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