Active: ما هي الحالة النشطة في دورة حياة iOS

المؤلف: IT Sectr نُشر: 2026-03-03 وقت القراءة: 10 دق

Active — الحالة النشطة لدورة حياة تطبيق iOS، حيث يكون في المقدمة، يستلم أحداث اللمس ويتفاعل مع المستخدم. دعنا نفهم كيف يعمل حالة Active، وما هي طرق UIApplicationDelegate المسؤولة عنها، وكيف يتم معالجة الانتقالات بين Active و Inactive في Swift بشكل صحيح.

النقاط الرئيسية

  • Active — التطبيق في المقدمة، UIResponder يستلم أحداث اللمس، التطبيق تفاعلي تماماً
  • applicationDidBecomeActive — الطريقة الرئيسية التي تشير إلى الانتقال إلى Active في iOS
  • ScenePhase.active — المكافئ في SwiftUI، يتم تتبعه عبر Environment values
  • العودة من Inactive — بعد مكالمة أو إشعار أو Control Center يصبح التطبيق Active مرة أخرى
  • الموارد — في Active للتطبيق أولوية قصوى للذاكرة ومعالج المركزي

Active: ما هي هذه الحالة

Active — حالة من دورة حياة التطبيق المحمول حيث يكون في المقدمة، يظهر على شاشة الجهاز ويتفاعل بنشاط مع المستخدم. في هذه الحالة، يتلقى التطبيق جميع أحداث اللمس، وضغطات المفاتيح، وبيانات مقياس التسارع والجيروسكوب، ولديه وصول كامل إلى معالج الرسومات لتصدير الواجهة.

في iOS، حالة Active هي جزء من نموذج دورة الحياة خماسي الحالات: Not Running → Inactive → Active → Inactive → Background → Suspended → Not Running. في Android، المكافئ هو حالة Activity بعد استدعاء onResume، عندما تكون Activity في قمة الكومة وتستقبل إدخال المستخدم. Active هي الحالة الوحيدة حيث تكون واجهة المستخدم تفاعلية تماماً وتستجيب للإيماءات والتمرير والنقر والرسوم المتحركة.

يمنح النظام التطبيق في حالة Active أولوية قصوى لمعالج المركزي والذاكرة عائلة التذبذب. هذا يعني أن النظام لن ينهي مثل هذا التطبيق عندما تكون الموارد منخفضة — سيتم تفريغ العمليات الخلفية والمعلقة أولاً. ولكن يجب على التطبيق استخدام الموارد بكفاءة لتجنب استنزاف البطارية وتسبب تقليل سرعة معالج المركزي.

بالنسبة للمستخدم، Active هي الحالة العادية للعمل مع التطبيق. يرى المستخدم الواجهة، ويمكنه الضغط على الأزرار، وملء النماذج، والتمرير في الخيط الزمني. أي مقاطعة لهذه الحالة (مكالمة، إشعار، تمرير للأعلى لفتح Control Center) تنقل التطبيق إلى Inactive، بعد ذلك يمكنه العودة إلى Active أو الذهاب إلى Background.

كيف يحدد النظام أن التطبيق Active

يستخدم iOS UIApplicationMain لإدارة الحالة. عند الانتقال إلى Active، يستدعي النظام applicationDidBecomeActive. بالنسبة لـ SwiftUI، الآلية المكافئة هي مراقبة scenePhase عبر Environment. يستخدم Android onResume كمؤشر لكون Activity في المقدمة. كلا النهجين يضمنان أن التطبيق يتلقى إشعاراً بتغير الحالة ويمكنه تكييف سلوكه.

المنصةالطريقة/الحدثSwift (UIKit)SwiftUIAndroid (Kotlin)
iOSالانتقال إلى ActiveapplicationDidBecomeActivescenePhase == .active
iOSالخروج من ActiveapplicationWillResignActivescenePhase == .inactive
Androidالانتقال إلى ActiveonResume()
Androidالخروج من ActiveonPause()

Active في iOS: Swift، UIKit و SwiftUI

في iOS، تتم معالجة حالة Active عبر UIApplicationDelegate. الطريقة الرئيسية هي applicationDidBecomeActive(_:). تتم استدعاؤها عند أول تشغيل للتطبيق وعند العودة من Inactive. هذه الطريقة هي المكان المثالي لاستئناف المهام التي تم إيقافها عند الدخول إلى Inactive: بدء الرسوم المتحركة، استئناف المؤقتات، إعادة تشغيل الحساسات، التحقق من تحديثات البيانات على الخادم.

UIKit: AppDelegate و SceneDelegate

مع iOS 13، قدمت Apple UISceneDelegate لدعم النوافذ المتعددة على iPad. في هذه الحالة، يتم استبدال applicationDidBecomeActive بـ sceneDidBecomeActive لكل مشهد فردي. يمكن للتطبيقات التي تدعم شاشة واحدة فقط مواصلة استخدام UIApplicationDelegate. كلا النهجين يتم استدعاؤهما عندما يصبح التطبيق أو المشهد نشطاً.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // أصبح التطبيق نشطاً — استئناف المهام
    func applicationDidBecomeActive(_ application: UIApplication) {
        resumeAnimations()
        restartTimers()
        refreshDataIfNeeded()
        startObservingSensors()
    }

    // التطبيق يفقد النشاط — إيقاف مؤقت
    func applicationWillResignActive(_ application: UIApplication) {
        pauseAnimations()
        stopTimers()
        saveDraftData()
    }

    private func resumeAnimations() {
        UIView.animate(withDuration: 0.3) {
            // استئناف رسوم الواجهة
        }
    }

    private func refreshDataIfNeeded() {
        let lastRefresh = UserDefaults.standard.object(forKey: "lastRefresh") as? Date ?? .distantPast
        if Date().timeIntervalSince(lastRefresh) > 300 {
            fetchDataFromServer()
        }
    }
}

يظهر الكود معالجة Active صحيحة في UIKit. applicationDidBecomeActive تستئنف الرسوم المتحركة والمؤقتات وتتحقق من احتياج تحديثات البيانات. applicationWillResignActive توقف كل شيء يمكن أن يستهلك الموارد وتحفظ المسودات. يضمن هذا الزوج من الطرق أن التطبيق يستجيب بشكل صحيح لتغيرات الحالة.

SwiftUI: scenePhase

SwiftUI ليس لديه AppDelegate — إدارة الحالة تتم عبر Environment<ScenePhase>. يتم تعيين القيمة .active عندما يكون المشهد في المقدمة وتفاعلياً. SwiftUI تعيد تشغيل الرسوم المتحركة والتحديثات تلقائياً عند العودة إلى Active. يحتاج المطور فقط إلى الاشتراك في onChange لتنفيذ الآثار الجانبية.

swift
import SwiftUI

@main
struct ActiveDemoApp: App {
    @Environment(\.scenePhase) private var scenePhase

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of: scenePhase) { oldPhase, newPhase in
            switch newPhase {
            case .active:
                print("أصبح المشهد نشطاً")
                resumeWork()
            case .inactive:
                print("أصبح المشهد غير نشط")
                pauseWork()
            case .background:
                print("ذهب المشهد إلى الخلفية")
                saveState()
            @unknown default:
                break
            }
        }
    }

    private func resumeWork() {
        // استئناف طلبات الشبكة، الرسوم المتحركة
    }

    private func pauseWork() {
        // إيقاف المهام الحساسة للوقت
    }

    private func saveState() {
        // حفظ حالة التطبيق
    }
}

في SwiftUI، scenePhase هي المصدر الوحيد للحقيقة حول حالة التطبيق. onChange تسمح بتنفيذ إجراءات عند كل انتقال. من المهم تذكر أن scenePhase متاحة فقط على iOS 14+ وفي SwiftUI Lifecycle. بالنسبة لتطبيقات UIKit بشاشات SwiftUI، استخدم نهج UIApplicationDelegate.

الانتقالات إلى حالة Active

Active يمكن الوصول إليه عبر عدة مسارات. الأول والأكثر وضوحاً هو البدء البارد: ينقر المستخدم على الأيقونة، ينتقل التطبيق من Not Running عبر Inactive إلى Active. الثاني هو العودة من الخلفية: يعود المستخدم إلى التطبيق عبر App Switcher، يمر التطبيق عبر Inactive ويصبح Active. الثالث هو العودة من مقاطعة مؤقتة: ينهي المستخدم مكالمة، أو يغلق Control Center، أو يستجيب لإشعار — يعود التطبيق من Inactive إلى Active.

سلسلة الانتقالات إلى Active

Not Running → Inactive → Active — بدء بارد. Background → Inactive → Active — عودة من الخلفية. Inactive → Active — عودة من مقاطعة مؤقتة. في كل حالة، يتم استدعاء applicationDidBecomeActive، ولكن السياق قد يختلف. في البدء البارد، يتم استدعاء didFinishLaunchingWithOptions قبل Active؛ عند العودة من الخلفية، يتم استدعاء willEnterForeground. يمكن للمطور استخدام هذه الاختلافات لاختيار استراتيجية استعادة الحالة.

السيناريومسار الانتقالCallbacks iOSCallbacks Android
بدء باردNot Running → ActivedidFinishLaunching → didBecomeActiveonCreate → onStart → onResume
عودة من الخلفيةBackground → ActivewillEnterForeground → didBecomeActiveonRestart → onStart → onResume
عودة من SuspendedSuspended → ActivewillEnterForeground → didBecomeActiveonRestart → onStart → onResume
بعد المقاطعةInactive → ActivedidBecomeActiveonResume

ملاحظة مهمة: عند العودة من Suspended، لا يستدعي iOS didFinishLaunchingWithOptions لأن التطبيق كان محمولاً فعلى في الذاكرة. هذا يعني أن كود التهيئة الموضوع في هذه الطريقة لا يتم تنفيذه مرة أخرى. كثيراً ما ينسى المطورون هذا وينقلون المنطق الحرج إلى applicationWillEnterForeground أو applicationDidBecomeActive لكلا السيناريوين.

Active في Android: دورة حياة Activity

في Android، مكافئ Active هو حالة Activity بعد استدعاء onResume(). تعتبر Activity نشطة عندما تكون في المقدمة وتستقبل إدخال المستخدم. تتوافق هذه الحالة مع قمة كومة Activity. إذا ظهرت Activity أخرى فوقها (حتى جزئياً)، تنتقل Activity الحالية إلى حالة onPause — مكافئ Inactive في iOS.

اختلاف رئيسي في Android هو أن عدة Activities يمكن أن تكون نشطة في نفس الوقت في وضع متعدد النوافذ (split screen، freeform). في هذه الحالة، تعتبر Activity التي يتفاعل معها المستخدم نشطة، بينما المجاورة موقوفة (onPause). iOS لا يدعم النوافذ المتعددة على iPhone، فقط على iPad عبر UIScene.

kotlin
class MainActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        // أصبح التطبيق نشطاً — استئناف المهام
        resumeCameraPreview()
        startLocationUpdates()
        activateSensors()
    }

    override fun onPause() {
        super.onPause()
        // التطبيق يفقد النشاط — تحرير الموارد
        releaseCamera()
        stopLocationUpdates()
        deactivateSensors()
    }

    private fun resumeCameraPreview() {
        // بدء معاينة الكاميرا (يتطلب إذناً)
        cameraProvider?.unbindAll()
        cameraProvider?.bindToLifecycle(
            this,
            cameraSelector,
            preview,
            imageAnalyzer
        )
    }

    private fun startLocationUpdates() {
        val locationRequest = LocationRequest.Builder(
            Priority.PRIORITY_HIGH_ACCURACY, 5000
        ).build()
        locationClient.requestLocationUpdates(
            locationRequest,
            locationCallback,
            Looper.getMainLooper()
        )
    }
}

يظهر الكود معالجة Active في Android عبر onResume/onPause. onResume تستئنف الكاميرا، والجيولوكيشن والحساسات — الموارد التي يجب أن تكون نشطة فقط عندما يكون التطبيق مرئياً للمستخدم. onPause تحرر هذه الموارد لتجنب استنزاف البطارية. API CameraX lifecycle-aware توقف المعاينة تلقائياً عند onPause.

أفضل الممارسات لمعالجة Active

القاعدة الأولى — لا تقم بعمليات ثقيلة في applicationDidBecomeActive أو onResume. تحميل البيانات، تحليل JSON، العمل مع قاعدة البيانات — كل هذا يجب أن يكون غير متزامن ولا يعطل الخيط الرئيسي. استخدم GCD (DispatchQueue) في iOS و Coroutines في Kotlin للمهام الخلفية. يجب على الخيط الرئيسي فقط تحديث الواجهة وبدء العمليات غير المتزامنة.

القاعدة الثانية — قم بمزامنة الحالة عند كل عودة إلى Active. قد يكون المستخدم قد غير الإعدادات في تطبيق النظام، أو تلقى إشعاراً دفعياً، أو حدث البيانات في تطبيق آخر. تحقق من حداثة الذاكرة المؤقتة عند الانتقال إلى Active — قد تكون البيانات قد قدمت خلال غياب المستخدم.

القاعدة الثالثة — لا تعتمد على Active كالحالة الوحيدة. يمكن للتطبيق تجاوز Active والانتقال مباشرة من Not Running إلى Background (إذا تم تشغيله في الوضع الخلفي). في iOS، يحدث هذا عند التشغيل عبر إشعار دفع مع خيار content-available. في Android، عند التشغيل عبر BroadcastReceiver. تحقق دائماً من الحالة الحالية قبل تنفيذ عمليات واجهة المستخدم.

القاعدة الرابعة — استخدم Activity Result API في Android بدلاً من onActivityResult. يتيح هذا معالجة نتيجة استدعاء الكاميرا أو المعرض أو الأذونات مباشرة في حالة Active دون فقدان البيانات عند إعادة إنشاء Activity. لـ iOS، استخدم async/await مع UIApplication.shared.open لحوارات النظام.

swift
import UIKit

final class ActiveStateManager {
    static let shared = ActiveStateManager()
    private var isActive = false

    func setActive(_ active: Bool) {
        isActive = active
        if active {
            NotificationCenter.default.post(name: .appDidBecomeActive, object: nil)
        }
    }

    func performWhenActive(_ block: @escaping () -> Void) {
        if isActive {
            block()
        } else {
            // تأجيل التنفيذ حتى العودة إلى Active
            NotificationCenter.default.addObserver(
                forName: .appDidBecomeActive,
                object: nil,
                queue: .main
            ) { _ in
                block()
            }
        }
    }
}

extension Notification.Name {
    static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
}

يظهر الكود مدير حالة Active يسمح لمكونات التطبيق الأخرى بالتحقق من الحالة النشطة الحالية. performWhenActive إما أن تنفذ الكتلة فوراً إذا كان التطبيق نشطاً، أو تؤجل التنفيذ حتى العودة إلى Active. هذا مفيد للخدمات التي تحتاج إلى تنفيذ إجراء بعد عودة المستخدم إلى التطبيق.

الأسئلة الشائعة

كم مرة يتم استدعاء applicationDidBecomeActive؟

يتم استدعاء الطريقة في كل مرة ينتقل فيها التطبيق إلى الحالة النشطة: عند أول تشغيل، عند العودة من الخلفية، بعد إغلاق Control Center أو Notification Center، بعد انتهاء مكالمة. في جلسة عادية يمكن استدعاؤها 5–10 مرات حسب إجراءات المستخدم. لا تضع التهيئة لمرة واحدة في هذه الطريقة.

ما الفرق بين Active و Visible في iOS؟

Visible هو مصطلح غير رسمي يعني أن التطبيق مرئي على الشاشة ولكنه قد لا يستلم الأحداث (على سبيل المثال، مغطى جزئياً بنافذة أخرى على iPad). Active هي الحالة الرسمية حيث يكون التطبيق مرئياً وتفاعلياً في نفس الوقت. على iPhone، التطبيق Visible هو دائماً Active؛ على iPad، من الممكن حالة Visible + Inactive.

ما هو didBecomeActive مقابل willEnterForeground؟

willEnterForeground يتم استدعاؤه عند العودة من الخلفية، ولكن التطبيق ليس نشطاً بعد — إنه في Inactive. didBecomeActive يتم استدعاؤه بعد أن يصبح التطبيق تفاعلياً تماماً. إذا كنت تحتاج إلى تنفيذ إجراء قبل أن يرى المستخدم الواجهة — استخدم willEnterForeground. إذا بعد العرض — استخدم didBecomeActive.

هل يمكن للتطبيق أن يكون Active بدون واجهة مرئية؟

لا. Active تعني أن التطبيق في المقدمة ويظهر على الشاشة. بدون واجهة مرئية، يمكن أن يكون التطبيق في Background أو Suspended. الاستثناء هو وضع متعدد النوافذ في iPad، حيث يمكن أن تكون نافذة واحدة نشطة والأخرى لا، ولكن كلتاهما مرئيتان. VoiceOver ومسجل الصوت لا يغيران هذه القاعدة.

كيف أختبر الانتقال إلى Active على المحاكي؟

على محاكي iOS، اضغط على Cmd+Shift+H للذهاب إلى الشاشة الرئيسية (يذهب التطبيق إلى Background)، ثم اضغط على أيقون التطبيق مرة أخرى. استخدم Cmd+L لقفل الشاشة (willResignActive) وفتحها (didBecomeActive). لاختبار Inactive، افتح Control Center (Cmd+Shift+; للوحة مفاتيح macOS) أو Notification Center.

الملخص

  • Active — حالة التطبيق في المقدمة مع وصول كامل لإدخال المستخدم وأولوية قصوى للموارد
  • iOS UIKit — applicationDidBecomeActive لاستئناف الرسوم المتحركة، المؤقتات والحساسات
  • SwiftUI — scenePhase .active عبر Environment، onChange للآثار الجانبية
  • Android — onResume/onPause كمكافئ Active/Inactive، مع دعم متعدد النوافذ
  • الانتقالات — يتم الوصول إلى Active من Not Running (بدء بارد)، Background و Inactive
  • الموارد — العمليات الثقيلة في didBecomeActive يجب أن تكون غير متزامنة، ولا تعطل الخيط الرئيسي
  • المزامنة — التحقق من حداثة الذاكرة المؤقتة والبيانات عند كل عودة إلى Active

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا