ARC در سوئیفت(Swift – ARC Overview)

توابع مدیریت حافظه و عملکرد آن در زبان Swift 4 از طریق شمارش مرجع خودکار (ARC) انجام می شود. از ARC برای مقدار دهی اولیه و حذف مقدار دهی اولیه منابع سیستم استفاده می شود در نتیجه فضای حافظه مورد استفاده در نمونههای کلاس استفاده میشود زمانی که نمونهها دیگر، مورد نیاز نیستند. ARC اطلاعات مربوط به روابط بین نمونه های کد را برای مدیریت مؤثر منابع حافظه ردیابی می کند.
عملکرد ARC
- ARC هر زمان که نمونه کلاس جدیدی توسط ()init ایجاد شود بخشی از حافظه را برای ذخیره اطلاعات به آن اختصاص می دهد.
- اطلاعات مربوط به نوع نمونه و مقادیر آن در حافظه ذخیره می شوند.
- هنگامی که دیگر به نمونه کلاس احتیاجی نباشد، به طور خودکار فضای حافظه را با استفاده از ()deinit برای ذخیره سازی بیشتر و بازیابی نمونه کلاس آزاد می کند.
- ARC ویژگی های نمونه کلاس موجود، ثابت ها و متغیرها را ردیابی کرده به طوری که ()deinit تنها برای موارد استفاده نشده اعمال می شود.
- ARC یک “مرجع قوی” برای آن دسته از ویژگی های نمونه کلاس، ثابت ها و متغیرها است که برای محدود کردن جابجایی نمونه کلاس های اجرایی استفاده می شود.
برنامه ARC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 2 |
Swift 4 98 |
نمونه های کلاس چرخه مرجع قوی ARC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 2 |
Initializing: Swift 4 Initializing: ARC |
نکته:
زبان برنامه نویسی سوئیفت از شمارش مرجع اتوماتیک (ARC) برای مدیریت حافظه استفاده می کند. Apple در گذشته نیاز به مدیریت حافظه دستی در Objective C داشت، اما ARC را در سال ۲۰۱۱ معرفی کرد که اجازه تخصیص و آزادسازی راحت تر حافظه را می دهد.
مراجع ناشناخته و ضعیف ARC
یکی از مشکلات ARC، احتمال ایجاد یک چرخه مرجع قوی است که نمونه های دو کلاس مختلف هر کدام به دیگری ارجاع دارند که باعث می شود در حافظه نشت کنند، زیرا هرگز آزاد نمی شوند. زبان برنامه نویسی سوئیفت کلمات کلیدی weak و unowned را برای حل چرخه های مرجع قوی فراهم کرده است:
- مراجع ضعیف(Weak)
- مراجع ناشناخته(Unowned)
از این منابع برای ارجاع موارد دیگر در یک چرخه مرجع توسط یک نمونه استفاده می شود. سپس ممکن است این موارد به جای اهمیت دادن به چرخه مرجع قوی، به هر یک از نمونه ها مراجعه کنند. هنگامی که کاربر بداند برخی از نمونه ها ممکن است مقادیر “nil” را برگردانند(مرجع های weak باید متغیرهای اختیاری باشند، زیرا می توانند تغییر کنند و nil شوند)، آن را با مرجع Weak و هنگامی که نمونه مقداری غیر از nil برگرداند، آن را با مرجع Unowned اعلام می کند.
برنامه مرجع ضعیف
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 2 |
ARC Is The Main Module Sub Module with its topic number is 4 |
برنامه مرجع ناشناس
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 2 |
ARC Marks Obtained by the student is 98 |
چرخه های مرجع قوی برای Closures
هنگامی که ما یک closure را به ویژگی نمونه کلاس و بدنه Closure اختصاص دهیم می توانیم یک چرخه مرجع قوی نمونه دریافت کنیم. نمونه قوی برای closure توسط “self.someProperty”یا “()self.someMethod” تعریف می شود. چرخه های مرجع قوی به عنوان انواع مرجع برای closure استفاده می شوند.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 |
<p>Welcome to Closure SRC</p> |
منابع ضعیف و ناشناخته
هنگامی که Closure و نمونه به یکدیگر رجوع شوند، کاربر ممکن است capture در یک Closure را به عنوان یک مرجع unowned تعریف کند که به کاربر اجازه نمی دهد نمونه را به طور همزمان تفکیک کند. هنگامی که مقدار بازگشتی یک نمونه “nil” نشان داده شود، Closure به عنوان یک نمونه weak تعریف می شود.
عیب یابی و عناصر دیگر
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
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 اجرا کنیم نتیجه زیر را می گیریم:
1 2 |
<Inside>ARC Weak References</Inside> Inside the deinit() |
این خبر را به اشتراک بگذارید :