Suspended — iOS ایپلیکیشن لائف سائیکل کی ایک معطل حالت جس میں ایپ میموری میں منجمد ہوتی ہے لیکن کوڈ پر عمل نہیں کرتی۔ ہم دکھاتے ہیں کہ Suspended کیسے کام کرتا ہے، پس منظر میں ایپ منجمد ہونے کے کیا خطرات ہیں، iOS Suspended ایپس کو ان لوڈ کرنے کا انتظام کیسے کرتا ہے، اور Suspended سے واپسی کے بعد ہموار بحالی کے لیے state restoration کیسے لاگو کریں۔
اہم نکات
Suspended iOS ایپلیکیشن لائف سائیکل کی ایک حالت ہے جس میں ایپ ڈیوائس کی RAM میں موجود ہوتی ہے لیکن کوئی کوڈ پر عمل نہیں کرتی۔ یہ مکمل خاتمے سے پہلے کی آخری حالت ہے: ایپ تمام پس منظر کے کاموں کو مکمل کرنے یا ٹائم آؤٹ ختم ہونے کے بعد Background سے Suspended میں منتقل ہوتی ہے۔ Suspended میں، ایپلیکیشن مکمل طور پر منجمد ہوتی ہے — تمام تھریڈ روک دیے جاتے ہیں، ٹائمر کام نہیں کرتے، اور کوئی نیٹ ورک سرگرمی نہیں ہوتی۔
Suspended iOS کی ایک منفرد خصوصیت ہے، جو معیاری Android لائف سائیکل میں موجود نہیں ہے۔ اس کی وجہ مختلف پروسیس مینجمنٹ آرکیٹیکچر میں ہے۔ iOS ایپ کی تصویر کو میموری میں محفوظ رکھتا ہے (ڈیسک ٹاپ ہائبرنیشن کی طرح) تاکہ جب صارف واپس آئے، انٹرفیس کو کولڈ اسٹارٹ کے بغیر فوری طور پر بحال کیا جا سکے۔ Android میں Suspended نہیں ہے — ایک پروسیس یا تو موجود ہے اور کوڈ پر عمل کر سکتی ہے (Background) یا ختم ہو چکی ہے (Not Running)، اگرچہ Android LMK کے ذریعے تھریڈ پر عمل روک سکتا ہے۔
صارف کے لیے، Suspended فوری بحالی کی طرح لگتا ہے: وہ App Switcher کے ذریعے ایپس کے درمیان سوئچ کرتے ہیں، اور ہر ایپ وہیں کھلتی ہے جہاں انہوں نے چھوڑا تھا۔ یہ وہم پیدا کرتا ہے کہ تمام ایپس بیک وقت چل رہی ہیں۔ حقیقت میں، ان میں سے زیادہ تر Suspended میں منجمد ہیں۔ Suspended سے ہاٹ اسٹارٹ Not Running سے کولڈ اسٹارٹ کے مقابلے میں کئی گنا تیز ہے، کیونکہ کوڈ پہلے سے میموری میں لوڈ ہے۔
iOS تمام ایپلیکیشنز کی حالت کو ٹریک کرتا ہے اور دستیاب میموری کی بنیاد پر Suspended ایپس کو ان لوڈ کرنے کا فیصلہ کرتا ہے۔ جب میموری کم ہوتی ہے، سسٹم Suspended ایپس کو ان لوڈ کرنا شروع کرتا ہے، ان سے شروع کرتا ہے جو اس حالت میں سب سے زیادہ دیر ہیں۔ اگر میموری اب بھی ناکافی ہو، سسٹم Background اور Inactive سے ایپس کو Suspended میں بعد میں ان لوڈ کرنے کے ساتھ منتقل کرتا ہے۔ یہ عمل صارف کے لیے مکمل طور پر شفاف ہے — وہ صرف App Switcher میں ایپ کا آئیکن دیکھتے ہیں، جو ٹیپ کرنے پر کولڈ اسٹارٹ شروع کرتا ہے۔
| خصوصیت | Suspended (iOS) | Background (iOS) | Background (Android) |
|---|---|---|---|
| کوڈ پر عمل کرتا ہے | نہیں | ہاں (محدود) | ہاں (محدود) |
| میموری میں | ہاں | ہاں | ہاں |
| CPU استعمال | 0% | کم | کم |
| ہاٹ اسٹارٹ | ہاں — فوری بحالی | ہاں — Inactive کے ذریعے | نہیں — عمل ختم ہو سکتا ہے |
| ٹائم آؤٹ | نہیں — گھنٹوں میموری میں رہ سکتا ہے | ~30 سیکنڈ (beginBackgroundTask کے بعد) | API ورژن پر منحصر |
| سسٹم کے ذریعے ان لوڈ | میموری کم ہونے پر | میموری شدید کم ہونے پر | LMK (Low Memory Killer) |
| کام پر واپسی | App Switcher سے — فوری | App Switcher سے — Inactive کے ذریعے | کولڈ اسٹارٹ |
| State Restoration | تجویز کردہ | ضروری نہیں | SavedStateHandle |
iOS میں، تمام پس منظر کے کاموں کو مکمل کرنے کے بعد Suspended خود بخود حاصل ہوتا ہے۔ سسٹم applicationDidEnterBackground کو کال کرتا ہے، beginBackgroundTask پر عمل کرنے کا وقت دیتا ہے (تقریباً 30 سیکنڈ)، پھر زبردستی تمام تھریڈ کو روکتا ہے اور ایپ کو Suspended میں منتقل کرتا ہے۔ میموری میں موجود اشیاء محفوظ رہتی ہیں، لیکن کوئی کوڈ پر عمل نہیں ہوتا — ایپلیکیشن اپنی موجودہ حالت میں منجمد ہوتی ہے۔
ایک انتہائی اہم نکتہ: applicationDidEnterBackground آخری طریقہ ہے جو Suspended سے پہلے یقینی طور پر کال کیا جاتا ہے۔ اس کے بعد، ایپ کو میموری ان لوڈ کے بارے میں کوئی اطلاع نہیں ملتی۔ اگر صارف یا سسٹم Suspended میں ایپ کو ختم کرتا ہے، تو نہ applicationWillTerminate اور نہ applicationDidEnterBackground دوبارہ کال کیا جاتا ہے۔ لہذا، تمام ڈیٹا سیونگ applicationDidEnterBackground میں ہونا چاہیے، applicationWillTerminate میں نہیں۔
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Suspended سے پہلے آخری یقینی کال
func applicationDidEnterBackground(_ application: UIApplication) {
// میموری ان لوڈ سے بچنے کے لیے ہر وہ چیز محفوظ کریں جس کی ضرورت ہے
savePersistentState()
saveNavigationStack()
// اگر ضرورت ہو تو اضافی وقت کی درخواست کریں
let task = application.beginBackgroundTask {
application.endBackgroundTask(task)
}
}
// Suspended سے واپسی — ہاٹ اسٹارٹ
func applicationWillEnterForeground(_ application: UIApplication) {
// ایپ Suspended میں تھی، کام دوبارہ شروع کرنا
print("Suspended یا Background سے واپسی")
}
// میموری ان لوڈ کے بعد مکمل بحالی
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// اگر یہ Suspended سے ان لوڈ کے بعد کولڈ اسٹارٹ ہے —
// state restoration بحال کریں
return true
}
private func savePersistentState() {
UserDefaults.standard.set(Date(), forKey: "lastActiveDate")
}
private func saveNavigationStack() {
guard let rootVC = window?.rootViewController else { return }
// موجودہ نیویگیشن اسٹیک محفوظ کریں
if let navController = rootVC as? UINavigationController {
let vcClasses = navController.viewControllers.map { type(of: $0) }
UserDefaults.standard.set(vcClasses.map { NSStringFromClass($0) }, forKey: "navStack")
}
}
}کوڈ iOS پر Suspended کے انتہائی اہم ہینڈلنگ کو دکھاتا ہے۔ applicationDidEnterBackground آخری یقینی کال ہے۔ تمام ڈیٹا سیونگ یہاں ہونا چاہیے: صارف کی حالت، نیویگیشن اسٹیک، ڈرافٹ، ٹائمر۔ applicationWillEnterForeground Suspended یا Background سے واپسی پر کال کیا جاتا ہے۔ didFinishLaunchingWithOptions — صرف کولڈ اسٹارٹ پر، جب ایپ کو Suspended کے بعد میموری سے ان لوڈ کیا گیا تھا۔
Android میں، iOS Suspended کا کوئی براہ راست مشابہ نہیں ہے۔ Android عمل کے سیاق و سباق کو محفوظ رکھتے ہوئے ایپس کو میموری میں منجمد نہیں کرتا۔ اس کے بجائے، Android یا تو عمل کو پس منظر میں رکھتا ہے یا اسے ختم کرتا ہے۔ تاہم، Android 11+ (API 30) پر App Freezer نامی ایک طریقہ کار متعارف کرایا گیا، جو SIGSTOP سگنل کا استعمال کرتے ہوئے پس منظر کے عمل کی انجام دہی کو روکتا ہے۔ یہ فنکشنل طور پر Suspended سے ملتا جلتا ہے، لیکن اہم فرقوں کے ساتھ۔
App Freezer Android میموری مینجمنٹ سسٹم کا حصہ ہے۔ جب کوئی ایپ فعال اطلاعوں کے بغیر طویل عرصے تک پس منظر میں رہتی ہے، سسٹم اسے SIGSTOP بھیجتا ہے، تمام تھریڈ روک دیتا ہے۔ جب ایپ پیش منظر میں واپس آتی ہے، SIGCONT بھیجا جاتا ہے اور عمل دوبارہ شروع ہوتا ہے۔ iOS سے بنیادی فرق: App Freezer حالت کے تحفظ کی ضمانت نہیں دیتا — منجمد کرنے کے دوران عمل ختم ہونے پر میموری میں ڈیٹا ضائع ہو سکتا ہے۔
Android پر، کسی بھی عمل کے خاتمے کے دوران خودکار حالت کے تحفظ کے لیے ViewModel میں SavedStateHandle استعمال کرنے کی سفارش کی جاتی ہے۔ SavedStateHandle onSaveInstanceState کے ذریعے Bundle میں ڈیٹا محفوظ کرتا ہے، جو App Freezer اور Process Death دونوں سے بچ جاتا ہے۔ iOS کے برعکس، جہاں Suspended سے ان لوڈ ایک غیر معمولی صورتحال ہے، Android پر Process Death ایک عام رویہ ہے جس کی ہمیشہ توقع کی جانی چاہیے۔
// SavedStateHandle — Android پر Process Death سے نجات
class CheckoutViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
// وہ حالت جو App Freezer کے بعد بھی عمل سے بچ جاتی ہے
var currentStep: MutableLiveData<Int> =
savedStateHandle.getLiveData("checkout_step", 1)
var cartItems: MutableLiveData<List<CartItem>> =
savedStateHandle.getLiveData("cart_items", emptyList())
fun proceedToNextStep() {
currentStep.value = (currentStep.value ?: 0) + 1
}
fun addToCart(item: CartItem) {
val updatedList = (cartItems.value ?: emptyList()) + item
cartItems.value = updatedList
savedStateHandle["cart_items"] = updatedList
}
}
// App Freezer کی صورت میں onStop میں محفوظ کریں
class MainActivity : AppCompatActivity() {
override fun onStop() {
super.onStop()
// وہ ڈیٹا محفوظ کریں جسے منجمد ہونے سے بچنا ہے
saveDraftData()
// منجمد حالت میں غیر ضروری وسائل خالی کریں
releaseHeavyResources()
// خبردار کریں کہ ایپ منجمد ہو جائے گی
// (ڈیبگنگ کے لیے لاگنگ)
Log.d("Lifecycle", "Activity stopped — ممکنہ App Freeze")
}
}کوڈ Android پر Suspended مشابہ کو سنبھالنے کا طریقہ دکھاتا ہے۔ ViewModel میں SavedStateHandle Process Death کے دوران خود بخود ڈیٹا محفوظ اور بحال کرتا ہے۔ onStop ممکنہ App Freezer یا عمل کے خاتمے سے پہلے آخری یقینی واقعہ ہے۔ چیک آؤٹ فارم کی حالت، کارٹ میں موجود اشیاء کی فہرست — یہ تمام ڈیٹا SavedStateHandle کی بدولت منجمد ہونے سے بچ جاتا ہے۔ بھاری وسائل (bitmaps، DB کرسر) کے لیے، onStop میموری خالی کرنے کی جگہ ہے۔
State Restoration iOS کا ایک بلٹ ان طریقہ کار ہے جو ایپ کو میموری سے ان لوڈ کرنے کے بعد UI حالت کو محفوظ اور بحال کرتا ہے۔ اگر ایپ Suspended میں تھی اور سسٹم نے اسے ان لوڈ کر دیا، تو اگلے کولڈ اسٹارٹ پر state restoration نیویگیشن اسٹیک، اسکرول پوزیشن، فارم کی حالت اور دیگر UI عناصر کو بحال کرتا ہے۔ صارف اسی اسکرین پر واپس آتا ہے جہاں اس نے چھوڑا تھا۔
State Restoration UIViewControllerRestoration اور UIStateRestoring پروٹوکول کے ذریعے کام کرتا ہے۔ ڈویلپر ہر ViewController اور View کو restorationIdentifier تفویض کرتا ہے جسے وہ بحال کرنا چاہتے ہیں۔ پس منظر میں جاتے وقت، iOS ان اشیاء کی حالت کو انکوڈ کرتا ہے۔ ان لوڈ کے بعد واپسی پر، iOS نئی اشیاء بناتا ہے اور محفوظ شدہ حالت کو ڈی کوڈ کرتا ہے۔ State restoration کے بغیر، صارف کولڈ اسٹارٹ کے بعد جہاں چھوڑا تھا وہاں کی بجائے خالی اسکرین دیکھے گا۔
import UIKit
class DetailViewController: UIViewController {
var itemID: String = ""
var scrollPosition: CGPoint = .zero
override func viewDidLoad() {
super.viewDidLoad()
restorationIdentifier = "DetailViewController"
restorationClass = type(of: self)
}
override func encodeRestorableState(with coder: NSCoder) {
super.encodeRestorableState(with: coder)
coder.encode(itemID, forKey: "itemID")
coder.encode(scrollPosition, forKey: "scrollPosition")
}
override func decodeRestorableState(with coder: NSCoder) {
super.decodeRestorableState(with: coder)
if let savedID = coder.decodeObject(forKey: "itemID") as? String {
itemID = savedID
loadItem()
}
if let savedPosition = coder.decodeCGPoint(forKey: "scrollPosition") {
scrollPosition = savedPosition
// ڈیٹا لوڈ کرنے کے بعد پوزیشن بحال کریں
}
}
}
// AppDelegate — State Restoration کو فعال کرنا
func application(
_ application: UIApplication,
shouldSaveSecureApplicationState coder: NSCoder
) -> Bool {
return true
}
func application(
_ application: UIApplication,
shouldRestoreSecureApplicationState coder: NSCoder
) -> Bool {
return true
}کوڈ iOS پر State Restoration کے نفاذ کو دکھاتا ہے۔ ہر بحال کیے جانے والے ViewController کے لیے restorationIdentifier اور restorationClass ضروری ہیں۔ encodeRestorableState/decodeRestorableState NSCoder کے ذریعے ڈیٹا محفوظ اور لوڈ کرتے ہیں۔ AppDelegate میں، shouldSaveSecureApplicationState اور shouldRestoreSecureApplicationState خفیہ کردہ حالت کے تحفظ کو فعال کرتے ہیں۔ iOS 12+ پر، ڈیٹا کے تحفظ کے لیے محفوظ انکوڈنگ (NSSecureCoding) استعمال کرنے کی سفارش کی جاتی ہے۔
پہلا قاعدہ — کبھی یہ فرض نہ کریں کہ ایپ Suspended سے واپس آئے گی۔ سسٹم کسی بھی وقت ایپ کو ان لوڈ کر سکتا ہے۔ تمام انتہائی اہم ڈیٹا Suspended میں منتقلی سے پہلے مستقل اسٹوریج میں محفوظ کیا جانا چاہیے — یعنی applicationDidEnterBackground یا onStop میں۔ UserDefaults, Core Data, File Manager — مناسب اسٹوریج کے اختیارات۔ میموری (متغیرات، خصوصیات) ان ڈیٹا کے لیے ناقابل اعتماد اسٹوریج ہے جنہیں Suspended سے بچنا ہے۔
دوسرا قاعدہ — Suspended سے پہلے وسائل خالی کریں۔ فائل ڈسکرپٹر بند کریں، GPU میموری (Metal, Core Graphics) خالی کریں، نیٹ ورک کنکشن بند کریں۔ اگرچہ ایپ Suspended میں CPU استعمال نہیں کرتی، لیکن قابض وسائل دوسری ایپلیکیشنز کے لیے مسدود ہوتے ہیں۔ iOS پر، Suspended میں کھلی ساکٹ نہیں رکھی جا سکتیں — Suspended سے واپسی پر وہ غیر فعال ہو سکتی ہیں، جس سے غلطیاں ہوتی ہیں۔
تیسرا قاعدہ — Suspended سے واپسی کے انتظار میں وقت پر منحصر منطق نہ رکھیں۔ ٹائمر، کال بیک اور نیٹ ورک سرگرمی Suspended میں رک جاتی ہے۔ اگر ایپ کئی گھنٹوں کے لیے Suspended میں رہی، تو واپسی پر ٹائمر غلط طریقے سے چل سکتا ہے۔ واپسی پر ڈیٹا کی درستی چیک کریں — کیشے پرانا ہو سکتا ہے اور اجازت نامہ ٹوکن ختم ہو سکتا ہے۔
چوتھا قاعدہ — تمام اسکرینوں کے لیے State Restoration استعمال کریں، خاص طور پر ان پٹ فارم، اسکرول ایبل فہرستوں اور تفصیل والی اسکرینوں کے لیے۔ State restoration کے بغیر، ان لوڈ شدہ Suspended سے واپسی کے بعد، صارف جہاں چھوڑا تھا وہاں کی بجائے ایپ کی ابتدائی اسکرین دیکھے گا۔ یہ صارف کے تجربے کو خراب کرتا ہے اور صارف کو اعادہ کرنے پر مجبور کرتا ہے۔
import UIKit
// چیک: کیا ایپ میموری سے ان لوڈ ہوئی تھی؟
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// چیک کریں کہ محفوظ شدہ حالت موجود ہے یا نہیں
if UserDefaults.standard.object(forKey: "navStack") != nil {
// ایپ Suspended سے ان لوڈ ہوئی تھی
// حالت بحال کرنے کی ضرورت ہے
restoreNavigationStack()
} else {
// Not Running سے صاف کولڈ اسٹارٹ
showOnboardingIfNeeded()
}
return true
}
private func restoreNavigationStack() {
guard let savedStack = UserDefaults.standard.array(forKey: "navStack") as? [String],
let navController = window?.rootViewController as? UINavigationController
else { return }
for vcClassName in savedStack {
if let vcClass = NSClassFromString(vcClassName) as? UIViewController.Type {
let vc = vcClass.init()
navController.pushViewController(vc, animated: false)
}
}
}کوڈ یہ تعین کرنے کا طریقہ دکھاتا ہے کہ آیا ایپ کو Suspended سے ان لوڈ کیا گیا تھا۔ محفوظ کردہ نیویگیشن اسٹیک کی موجودگی کے لیے UserDefaults چیک کرنا ان لوڈ کے بعد کولڈ اسٹارٹ کو صاف کولڈ اسٹارٹ سے ممتاز کرنے کی اجازت دیتا ہے۔ پہلے صورت میں، نیویگیشن اسٹیک بحال کیا جاتا ہے؛ دوسرے میں، آن بورڈنگ یا مرکزی اسکرین دکھائی جاتی ہے۔ یہ طریقہ ان صورتوں کے لیے بلٹ ان State Restoration کو مکمل کرتا ہے جہاں NSCoder ناکافی ہے۔
اکثر پوچھے گئے سوالات
لا محدود — چند سیکنڈ سے کئی دنوں تک۔ iOS کے پاس Suspended کے لیے کوئی ٹائم آؤٹ نہیں ہے۔ ایپ اس وقت تک میموری میں رہے گی جب تک سسٹم وسائل کی کمی کی وجہ سے اسے ان لوڈ کرنے کا فیصلہ نہیں کرتا۔ عملی طور پر، ایپس ڈیوائس کی RAM اور فعال ایپلیکیشنز کی تعداد کے لحاظ سے 15 منٹ سے کئی گھنٹوں تک Suspended میں رہتی ہیں۔
نہیں۔ Suspended سے ایپ ان لوڈ کرتے وقت applicationWillTerminate کال نہیں کیا جاتا۔ سسٹم ایپ کو مطلع کیے بغیر صرف میموری خالی کرتا ہے۔ یہ ایک اور وجہ ہے کہ تمام ڈیٹا سیونگ applicationDidEnterBackground میں ہونا چاہیے۔ applicationWillTerminate صرف اس وقت کال کیا جاتا ہے جب صارف App Switcher سے ایپ کو سوائپ کرکے دستی طور پر ختم کرتا ہے۔
کوئی براہ راست مشابہ نہیں ہے۔ Android 11+ پر، App Freezer متعارف کرایا گیا، جو SIGSTOP کے ذریعے پس منظر کے عمل کو روکتا ہے — یہ فنکشنل طور پر Suspended سے ملتا جلتا ہے۔ تاہم، Android ایپس کو کسی بھی وقت Process Death کے امکان کے ساتھ ڈیزائن کیا جانا چاہیے۔ حالت کو محفوظ کرنے کے لیے ViewModel میں SavedStateHandle اور onSaveInstanceState استعمال کریں جو App Freezer اور Process Death دونوں سے بچے گی۔
iOS میں چیک کرنے کے لیے کوئی براہ راست API نہیں ہے۔ ایک بالواسطہ طریقہ: didFinishLaunchingWithOptions میں محفوظ شدہ حالت کی موجودگی کے لیے UserDefaults چیک کریں۔ اگر حالت موجود ہے — ایپ Suspended سے ان لوڈ ہوئی تھی اور کولڈ اسٹارٹ کر رہی ہے۔ اگر حالت موجود نہیں ہے — صاف کولڈ اسٹارٹ۔ SwiftUI میں، scenePhase.background میں ایک فلیگ محفوظ کیا جا سکتا ہے اور اگلے لانچ پر چیک کیا جا سکتا ہے۔
Suspended میں منتقلی کے وقت، iOS ایک سنیپ شاٹ لیتا ہے — موجودہ ایپ UI کا اسکرین شاٹ۔ یہ اسکرین شاٹ App Switcher میں اور ایپ پر واپسی پر (“پگھلنے” اینیمیشن کے طور پر) دکھایا جاتا ہے۔ اگر ایپ میں خفیہ ڈیٹا ہے، تو سنیپ شاٹ اسے ظاہر کر سکتا ہے۔ تحفظ کے لیے، UIApplication.shouldSnapshotSecureApp (iOS 16+) استعمال کریں یا applicationDidEnterBackground میں بلر اوورلے لگائیں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں