Swift - ภาพรวม ARC

ฟังก์ชันการจัดการหน่วยความจำและการใช้งานได้รับการจัดการในภาษา Swift 4 ผ่านการนับการอ้างอิงอัตโนมัติ (ARC) 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)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Swift 4
98

ARC Strong Reference Cycles Class Instances

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 การอ้างอิงที่อ่อนแอและไม่เป็นที่รู้จัก

คุณสมบัติประเภทคลาสมีสองวิธีในการแก้ไขวงจรอ้างอิงที่แข็งแกร่ง -

  • การอ้างอิงที่อ่อนแอ
  • การอ้างอิงที่ไม่เป็นที่รู้จัก

การอ้างอิงเหล่านี้ใช้เพื่อให้อินสแตนซ์หนึ่งอ้างอิงอินสแตนซ์อื่น ๆ ในรอบการอ้างอิง จากนั้นอินสแตนซ์อาจอ้างถึงแต่ละอินสแตนซ์แทนที่จะสนใจวงจรการอ้างอิงที่รัดกุม เมื่อผู้ใช้ทราบว่าอินสแตนซ์บางรายการอาจส่งคืนค่า 'ศูนย์' เราอาจชี้ว่าใช้การอ้างอิงที่ไม่เหมาะสม เมื่ออินสแตนซ์จะส่งคืนบางสิ่งแทนที่จะเป็นศูนย์ให้ประกาศด้วยข้อมูลอ้างอิงที่ไม่เป็นที่รู้จัก

โปรแกรมอ้างอิงที่อ่อนแอ

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>

การอ้างอิงที่อ่อนแอและไม่เป็นที่รู้จัก

เมื่อการปิดและอินสแตนซ์อ้างถึงซึ่งกันและกันผู้ใช้อาจกำหนดการจับในการปิดเป็นการอ้างอิงที่ไม่มีเจ้าของ จากนั้นจะไม่อนุญาตให้ผู้ใช้ยกเลิกการจัดสรรอินสแตนซ์ในเวลาเดียวกัน เมื่ออินสแตนซ์บางครั้งส่งคืนค่า 'ศูนย์' ให้กำหนดการปิดด้วยอินสแตนซ์ที่อ่อนแอ

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