Memory Graph، Xcode Debug Navigator کا ایک بصری ٹول ہے جو ایپلیکیشن کی میموری میں موجود اشیاء کو ان کے باہمی حوالہ جات کے ساتھ گراف کے طور پر ظاہر کرتا ہے۔ heap dump کے برعکس، Memory Graph صرف اشیاء کی فہرست نہیں دکھاتا بلکہ ایک ہدایت یافتہ حوالہ گراف دکھاتا ہے جہاں ہر نوڈ ایک آبجیکٹ ہے اور ہر کنارہ ایک حوالہ (strong, weak, unowned) ہے۔ Apple WWDC 2018 کے مطابق، یہ ٹول heap dump کے خام ڈیٹا کا تجزیہ کیے بغیر سیکنڈوں میں retain cycles اور میموری لیک کو بصری طور پر دریافت کرنے کی اجازت دیتا ہے۔
اہم نکات
Memory Graph Xcode Debug Navigator کا ایک جزو ہے (Xcode 10، WWDC 2018 میں متعارف کرایا گیا) جو ڈیبگ کیے جانے والے عمل کی میموری میں تمام اشیاء کا ایک ہدایت یافتہ گراف بناتا ہے۔ گراف کا ہر نوڈ ایک کلاس انسٹینس (Objective-C یا Swift) ہے، ہر کنارہ دوسری آبجیکٹ کا حوالہ ہے۔ کنارے کا رنگ حوالہ کی قسم کی نشاندہی کرتا ہے: نیلا — strong، سبز — weak، سرمئی — unowned۔ گراف LLDB اور Objective-C runtime ڈیٹا کی بنیاد پر بنایا جاتا ہے، لہذا مناسب کام کے لیے ایپلیکیشن کو ڈیبگ کنفیگریشن میں فعال علامات کے ساتھ مرتب کیا جانا چاہیے۔
کام کرنے کا اصول: جب ایپلیکیشن بریک پوائنٹ پر روکی جاتی ہے، Xcode LLDB کے ذریعے runtime سے تمام زندہ اشیاء اور ان کے حوالہ جات کی درخواست کرتا ہے۔ LLDB مکمل گراف بنانے کے لیے objc_getClassList اور مختص علاقوں پر تکرار کا استعمال کرتا ہے۔ ARM64 (Apple Silicon) پر، سست روی کے بغیر مختص ٹریکنگ کے لیے اضافی ہارڈویئر ذرائع استعمال کیے جاتے ہیں۔ گراف بنانے کا وقت ڈھیر کے سائز پر منحصر ہے: ایک عام iOS ایپلیکیشن (50–200 MB) کے لیے، گراف 1–3 سیکنڈ میں بنتا ہے۔
Apple کے مطابق، Memory Graph واحد ٹول ہے جو کوڈ میں ترمیم یا آلات سازی شامل کیے بغیر retain cycles کو بصری بنا سکتا ہے۔ Instruments Leaks کے برعکس، Memory Graph Xcode کے اندر ریئل ٹائم میں کام کرتا ہے اور الگ پروفائلر لانچ کی ضرورت نہیں ہوتی۔ یہ اسے ترقی کے دوران فوری میموری لیک تشخیص کے لیے پہلا انتخاب کا ٹول بناتا ہے۔
Heap dump تمام اشیاء کی اعداد (shallow size, retained size) کے ساتھ ایک جدول فراہم کرتا ہے — یہ مقداری تجزیہ کے لیے بہترین ہے۔ Memory Graph کنکشنز کی ایک بصری تصویر فراہم کرتا ہے — چکری حوالہ جات تلاش کرنے کے لیے بہترین ہے۔ یہ ٹولز ایک دوسرے کے تکمیلی ہیں: پہلے فوری retain cycle کا پتہ لگانے کے لیے Memory Graph، پھر درست retained size پیمائش کے لیے Instruments Allocations کے ذریعے heap dump۔ objc.io کے مطابق، دونوں طریقوں کا مجموعہ 95% میموری لیک منظرناموں کا احاطہ کرتا ہے۔
Retain cycle ایک ایسی صورت حال ہے جب دو یا زیادہ اشیاء ایک دوسرے کو strong حوالہ جات سے پکڑتی ہیں، ایک بند لوپ بناتی ہیں۔ ARC اس طرح کے لوپ کو ڈی لوکیٹ نہیں کر سکتا کیونکہ ہر آبجیکٹ کا retain count کبھی صفر تک نہیں پہنچتا۔ ایک کلاسک مثال: ViewController اور View، جہاں View کے پاس ایک closure کا strong حوالہ ہے جو self (ViewController) کو کیپچر کرتا ہے۔ Memory Graph اس طرح کے لوپ کو حلقوں (سائیکل) کے طور پر ظاہر کرتا ہے، فوری شناخت کے لیے انہیں نمایاں کرتا ہے۔
جب Xcode retain cycle کا پتہ لگاتا ہے، تو وہ اسے نارنجی خاکہ سے نمایاں کرتا ہے اور Debug Navigator میں انتباہ دکھاتا ہے۔ سائیکل پر کلک کرنے سے بند لوپ بنانے والی حوالہ جات کی زنجیر ظاہر ہوتی ہے۔ ڈویلپر کو صرف یہ طے کرنا ہوتا ہے کہ کون سا strong کنارہ weak ہونا چاہیے — عام طور پر یہ چائلڈ آبجیکٹ سے پیرنٹ کا حوالہ ہوتا ہے (جیسے delegate یا closure)۔
class ViewController: UIViewController {
let service = DataService()
override func viewDidLoad() {
super.viewDidLoad()
// ❌ Retain cycle: ViewController → service → closure → ViewController
service.fetchData { self.updateUI($0) }
}
func updateUI(_ data: Data) {}
}
class DataService {
var completion: ((Data) -> Void)?
func fetchData(handler: @escaping (Data) -> Void) {
self.completion = handler
}
}
Memory Graph میں آپ ایک مثلث دیکھیں گے: ViewController → DataService → closure → ViewController۔ حل self کے کیپچر کو کمزور بنانا ہے: [weak self]۔ اصلاح کے بعد، Memory Graph closure سے ViewController تک ایک سبز کنارہ دکھائے گا، اور retain cycle غائب ہو جائے گا۔
// درست شده کوڈ — self کا کمزور کیپچر
service.fetchData { [weak self] data in
guard let self else { return }
self.updateUI(data)
}
Memory Graph Debugger کا انٹرفیس تین پینلز پر مشتمل ہے: بایاں — تمام زندہ اشیاء کی فہرست (کلاس کے مطابق گروہ بند) انسٹینس گنتی کے ساتھ؛ مرکز — گھسیٹنے کے قابل نوڈس کے ساتھ ایک بصری گراف؛ دایاں — منتخب آبجیکٹ یا کنارے کے لیے ایک انسپکٹر۔ آبجیکٹ کی فہرست ظاہر کرتی ہے: کلاس آئیکن، میموری میں انسٹینس کی تعداد، کل retained size اور پورے ڈھیر کا فیصد۔ کلاس کے نام کے مطابق فلٹرنگ ریگولر ایکسپریشن کو سپورٹ کرتی ہے۔
گراف کے نوڈس کو پڑھنے کی اہلیت بہتر بنانے کے لیے گھسیٹا جا سکتا ہے۔ کسی نوڈ پر ڈبل کلک کرنے سے آبجیکٹ کے بارے میں تفصیلی معلومات کھلتی ہیں: اقسام اور اقدار کے ساتھ اس کی تمام خصوصیات، ہر خصوصیت کے لیے کال اسٹیک (backtrace)، اور retain/release تاریخ۔ Backtrace ایک اہم خصوصیت ہے: یہ دکھاتا ہے کہ کوڈ کی کونسی سطر نے آبجیکٹ کا حوالہ قائم کیا۔ یہ دستی طور پر تمام کوڈ کا جائزہ لیے بغیر لیک کا ماخذ تلاش کرنے کی اجازت دیتا ہے۔
پیچیدہ گراف کے لیے، Xcode Layout → Hierarchical یا Cluster کے ذریعے خودکار ترتیب فراہم کرتا ہے۔ درجہ بندی کی ترتیب جڑ کی اشیاء کو اوپر اور چائلڈ کو نیچے رکھتی ہے، زنجیر کی تلاش کو آسان بناتی ہے۔ کلسٹر گروپ بندی متعلقہ اشیاء کو کلسٹر میں گروپ کرتی ہے، جو اس وقت مفید ہے جب گراف میں کئی الگ تھلگ گروپ ہوں۔ Apple کے مطابق، زیادہ تر ایپلیکیشنز کے لیے درجہ بندی کی ترتیب تجویز کی جاتی ہے — یہ بدیہی ہے اور بصری تجزیہ میں کم وقت لیتی ہے۔
// LLDB کمانڈز جو Memory Graph اندرونی طور پر استعمال کرتا ہے
(lldb) script import lldb.macosx.heap
(lldb) script heap.find_variable("viewController")
0x600000c4b80: ViewController
(lldb) script heap.refs 0x600000c4b80
0x600000c4b80 -> 0x600003a4c00 (DataService)
ivar: _service, offset: 16
Memory Graph تجزیہ کے لیے ایک منظم نقطہ نظر میں کئی مراحل شامل ہیں۔ مرحلہ 1: ایپلیکیشن چلائیں، ایک منظر نامہ انجام دیں جو ممکنہ طور پر لیک کا سبب بنتا ہے (اسکرین کھولیں/بند کریں، نیٹ ورک کی درخواست کریں)۔ مرحلہ 2: Debug Navigator میں Memory Graph بٹن دبائیں — Xcode گراف بناتا ہے۔ مرحلہ 3: بائیں پینل میں نارنجی retain cycle انتباہات کی جانچ کریں۔ مرحلہ 4: مشکوک اشیاء کے لیے، Show only cycles آپشن استعمال کریں — صرف چکری حوالہ جات میں شامل نوڈس ظاہر ہوں گے۔
ایک بار retain cycle مل جانے کے بعد، سائیکل کے کنارے پر کلک کریں اور انسپکٹر پینل کھولیں۔ Backtrace سیکشن اس لمحے کال اسٹیک دکھاتا ہے جب یہ حوالہ قائم کیا گیا تھا۔ مثال کے طور پر، اگر کنارہ closure سے self کی طرف جاتا ہے، backtrace دکھائے گا کہ کس طریقہ میں اور کوڈ کی کس سطر پر closure بنایا گیا تھا۔ یہ قیاس آرائی کی ضرورت کو ختم کرتا ہے — آپ فوراً وہ نقطہ دیکھتے ہیں جہاں مسئلہ زدہ حوالہ بنایا گیا تھا۔ WWDC Labs کے مطابق، backtrace تجزیہ retain cycle کی تشخیص کے وقت کو 15–20 منٹ سے کم کر کے 2–3 منٹ کر دیتا ہے۔
class ProfileViewController: UIViewController {
var profileView: ProfileView!
override func viewDidLoad() {
super.viewDidLoad()
profileView = ProfileView()
// Memory Graph یہاں retain cycle دکھائے گا
profileView.onTap = { [unowned self] in
// ⚠️ unowned self کے nil ہونے پر crash کا سبب بن سکتا ہے
self.navigateToDetail()
}
}
func navigateToDetail() { }
}
// ✅ درست: [weak self] + guard let self
profileView.onTap = { [weak self] in
guard let self else { return }
self.navigateToDetail()
}
Memory Graph ہزاروں اشیاء ظاہر کر سکتا ہے، تلاش کو مشکل بنا دیتا ہے۔ بائیں پینل میں فلٹر استعمال کریں: کلاس کا نام درج کریں (جیسے ProfileViewController) صرف اس کلاس کے انسٹینس ظاہر کرنے کے لیے۔ پھر ایک انسٹینس منتخب کریں جسے ڈی لوکیٹ ہو جانا چاہیے تھا (اگر اسکرین بند ہے لیکن آبجیکٹ باقی ہے)۔ Show Reachable From لگائیں — صرف اس آبجیکٹ سے متعلقہ حوالہ جات ظاہر ہوں گے، باقی گراف چھپ جائے گا۔
تجربہ کار ڈویلپر Memory Graph کو نہ صرف لیک تلاش کرنے کے لیے بلکہ فعال میموری کنٹرول کے لیے بھی استعمال کرتے ہیں۔ ہر بڑی آرکیٹیکچر تبدیلی کے بعد Memory Graph چیک کریں — نیا delegate، closure یا NotificationCenter سبسکرپشن شامل کرنا۔ بس ایک عام منظر نامہ چلائیں اور یقینی بنائیں کہ اشیاء صحیح طریقے سے ڈی لوکیٹ ہو رہی ہیں اور retain cycles غیر موجود ہیں۔ اس میں 2–3 منٹ لگتے ہیں لیکن بعد میں گھنٹوں کی ڈیبگنگ کو روکتا ہے۔
Xcode میں Memory Report (Debug Navigator ٹیب) ریئل ٹائم میں میموری استعمال کا گراف دکھاتا ہے۔ اسے Memory Graph کے ساتھ استعمال کریں: تیز استعمال میں اضافے پر Memory Graph کھولیں۔ مثال کے طور پر، تصاویر لوڈ کرنے والے سیلز والی لمبی فہرست کو اسکرول کرتے وقت، Memory Graph دکھائے گا کہ کون سی اشیاء بن رہی ہیں اور کون سی ڈی لوکیٹ ہو رہی ہیں۔ اگر اشیاء کی تعداد کم ہونے کے بغیر بڑھتی ہے — یہ ایک ممکنہ لیک ہے جو کریش ہونے سے پہلے نظر آتی ہے۔ Apple کے مطابق، Memory Graph + Memory Report کا امتزاج Xcode 12 سے تمام iOS ڈویلپرز کے لیے تجویز کردہ ورک فلو ہے۔
// Objective-C میں delegation کے ذریعے لیک کی مثال
@interface DownloadManager : NSObject
@property (strong) id delegate; // ❌ weak ہونا چاہیے!
@end
@implementation DownloadManager
// Memory Graph retain cycle دکھائے گا:
// ViewController → DownloadManager.delegate → ViewController
@end
// درستی: weak property
@property (weak) id delegate;
خاص توجہ closures پر دیں — Swift میں retain cycles کا سب سے عام ذریعہ۔ کسی آبجیکٹ کی خاصیت کے طور پر محفوظ کردہ closure کے اندر self کیپچر کرنے پر ایک کلاسک سائیکل بنتا ہے۔ Memory Graph اسے ایک closure ({} علامت والا نوڈ) کے طور پر ظاہر کرتا ہے جو کیپچر کردہ اشیاء سے نیلے کناروں سے جڑا ہوتا ہے۔ تمام closures کو باقاعدگی سے چیک کریں، خاص طور پر وہ جو غیر متزلزل کالز، GCD، Combine اور SwiftUI میں استعمال ہوتے ہیں۔ Point-Free کے اعدادوشمار کے مطابق، Swift پروجیکٹس میں 90% لیک self کو کیپچر کرنے والے closures سے متعلق ہیں۔
اکثر پوچھے گئے سوالات
Memory Graph دونوں زبانوں کے لیے کام کرتا ہے کیونکہ یہ Objective-C runtime استعمال کرتا ہے۔ ObjC کے ساتھ مطابقت رکھنے والی Swift اشیاء (@objc سے نشان زد NSObject ذیلی طبقات) مکمل طور پر ظاہر ہوتی ہیں۔ ObjC پل کے بغیر خالص Swift ساخت اور کلاسز محدود طور پر دکھائی دیتی ہیں۔
اشیاء کو Objective-C runtime میں رجسٹرڈ ہونا چاہیے۔ Swift ویلیو ٹائپس (struct, enum) ظاہر نہیں ہوتیں۔ یقینی بنائیں کہ کلاس NSObject سے وراثت پاتی ہے یا Memory Graph میں نمائش کے لیے @objc وصف استعمال کرتی ہے۔
نیلا — strong حوالہ، آبجیکٹ کو برقرار رکھتا ہے۔ سبز — weak حوالہ، زندگی کے دور کو متاثر نہیں کرتا۔ سرمئی — unowned حوالہ۔ Retain cycle صرف نیلے کناروں سے بنتا ہے۔
گراف بنانا ایپلیکیشن کو 1–3 سیکنڈ کے لیے روکتا ہے اور عارضی طور پر Xcode میموری استعمال کو 200–500 MB تک بڑھا سکتا ہے۔ ایپلیکیشن خود سست نہیں ہوتی کیونکہ معائنہ بریک پوائنٹ کے توقف کے دوران ہوتا ہے۔
Xcode براہ راست گراف برآمد کرنے کی حمایت نہیں کرتا۔ دستاویزات کے لیے اسکرین شاٹ یا پروگرامیٹک ڈیٹا نکالنے کے لیے lldb اسکرپٹ heap.find_variable استعمال کریں۔ تفصیلی تجزیہ کے لیے، heap dump کے ساتھ Instruments Allocations استعمال کریں۔
خلاصہ
{} نوڈس کے طور پر ظاہر کرتا ہے۔ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں