سؤال

أنا أقوم ببرمجة تطبيق iPhone، وأحتاج إلى إجباره على الخروج بسبب إجراءات معينة للمستخدم.بعد تنظيف الذاكرة المخصصة للتطبيق، ما هي الطريقة المناسبة للاتصال لإنهاء التطبيق؟

هل كانت مفيدة؟

المحلول

هل جربت exit(0)?

بدلاً عن ذلك، [[NSThread mainThread] exit], ، على الرغم من أنني لم أحاول أن يبدو أن الحل الأكثر ملاءمة.

نصائح أخرى

على iPhone لا يوجد مفهوم للتوقف عن التطبيق. الإجراء الوحيد الذي يجب أن يتسبب في ترك التطبيق هو لمس زر الصفحة الرئيسية على الهاتف ، وهذا ليس شيئًا يمكن للمطورين الوصول إليه.

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

يظهر Exit (0) للمستخدم مع تعطل ، لذلك أظهر رسالة تأكيد للمستخدم. بعد تعليق التأكيد (زر الصفحة الرئيسية ، اضغط برمجيًا) وانتظر ثانيتين بينما يسير التطبيق في الخلفية مع الرسوم المتحركة ثم الخروج خلف عرض المستخدم

-(IBAction)doExit
{
    //show confirmation message to user
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Confirmation"
                                                 message:@"Do you want to exit?"
                                                delegate:self
                                       cancelButtonTitle:@"Cancel"
                                       otherButtonTitles:@"OK", nil];
    [alert show];
}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != 0)  // 0 == the cancel button
    {
        //home button press programmatically
        UIApplication *app = [UIApplication sharedApplication];
        [app performSelector:@selector(suspend)];

        //wait 2 seconds while app is going background
        [NSThread sleepForTimeInterval:2.0];

        //exit app when app is in background
        exit(0);
    }
}

إنها ليست حقًا وسيلة للإقلاع عن البرنامج ، ولكنها طريقة لإجبار الناس على الإقلاع عن التدخين.

UIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[anAlert show];

تحقق من سؤال وجواب هنا: https://developer.apple.com/library/content/qa/qa1561/_index.html

س: كيف يمكنني ترك تطبيق iOS برمجيًا؟

لا يوجد واجهة برمجة تطبيقات يتم توفيرها لإنهاء تطبيق iOS بأمان.

في iOS ، يضغط المستخدم على زر الصفحة الرئيسية لإغلاق التطبيقات. إذا كان للتطبيق شروط لا يمكن أن يوفر فيها وظيفته المقصودة ، فإن النهج الموصى به هو عرض تنبيه للمستخدم الذي يشير إلى طبيعة المشكلة والإجراءات المحتملة التي يمكن للمستخدم اتخاذها - تشغيل WiFi ، وتمكين خدمات الموقع ، إلخ. اسمح للمستخدم بإنهاء التطبيق وفقًا لتقديره الخاص.

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

بالإضافة إلى ذلك ، قد لا يتم حفظ البيانات ، لأن -applicationWillTerminate: ومماثلة UIApplicationDelegate لن يتم استدعاء الأساليب إذا اتصلت بالخروج.

إذا كان أثناء التطوير أو الاختبار ضروريًا لإنهاء التطبيق الخاص بك ، abort وظيفة ، أو assert ينصح الماكرو

انتقل إلى info.plist وتحقق من المفتاح "لا يتم تشغيل التطبيق في الخلفية". هذه المرة عندما ينقر المستخدم على زر الصفحة الرئيسية ، يخرج التطبيق تمامًا.

يضيف UIApplicationExitsOnSuspend الممتلكات على application-info.plist إلى true.

بعد بعض الاختبارات ، يمكنني أن أقول ما يلي:

  • باستخدام الواجهة الخاصة: [UIApplication sharedApplication] سوف يتسبب في أن التطبيق يبدو وكأنه تحطم ، لكنه سيتصل - (void)applicationWillTerminate:(UIApplication *)application قبل القيام بذلك
  • استخدام exit(0); سيقوم أيضًا بإنهاء التطبيق ، لكنه سيبدو "طبيعيًا" (يبدو أن أيقونات النقد - (void)applicationWillTerminate:(UIApplication *)application طريقة تفويض.

نصيحتي:

  1. اتصل يدويًا - (void)applicationWillTerminate:(UIApplication *)application على المندوب.
  2. مكالمة exit(0);.

يتم إخطار ApplicationDelegate الخاص بك عن الإقلاع عن التدخين المتعمد من قبل المستخدم:

- (void)applicationWillResignActive:(UIApplication *)application {

عندما أحصل على هذا الإشعار ، أتصل فقط

        exit(0);

الذي يفعل كل العمل. وأفضل شيء هو ، هو نية المستخدمين ، وهذا هو السبب في أن هذا لا ينبغي أن يكون مشكلة تسميها هناك.

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

لذا بدلاً من ذلك ، قمت بتعيين علامة لإنهاء التطبيق حقًا في إجراء الخلفية التالي. لا بأس في تحديث التطبيق بعد المزامنة.

تم رفض تطبيقي مؤخرًا قبل الميلاد ، لقد استخدمت طريقة غير موثقة. حرفياً:

"لسوء الحظ ، لا يمكن إضافته إلى متجر التطبيقات لأنه يستخدم واجهة برمجة تطبيقات خاصة. استخدام واجهات برمجة التطبيقات غير الحكومية ، والتي يتم حظرها كما هو موضح في اتفاقية ترخيص برنامج iPhone 3.3.1:

"3.3.1 لا يجوز التطبيقات استخدام واجهات برمجة التطبيقات الموثقة فقط بالطريقة التي تحددها Apple ويجب ألا تستخدم أو استدعاء أي واجهات برمجة تطبيقات خاصة."

API غير الجمهورية التي يتم تضمينها في طلبك يتم إنهاءها مع "

تقول أبل:

"تحذير: لا تتصل بوظيفة الخروج. ستظهر تطبيقات استدعاء الخروج للمستخدم لتحطمها ، بدلاً من أداء إنهاء رشيق والعودة إلى الشاشة الرئيسية."

أعتقد أن هذا افتراض سيء. إذا انقر المستخدم على زر إنهاء وظهرت رسالة تقول شيئًا مثل: "سيتم الإقلاع عن التطبيق الآن." ، لا يبدو أنه قد تم تحطيمه. يجب أن توفر Apple طريقة صالحة لإنهاء التطبيق (وليس الخروج (0)).

لقد حصل هذا على إجابة جيدة ولكنه قرر التوسع قليلاً:

لا يمكنك قبول التطبيق الخاص بك على AppStore دون قراءة إرشادات واجهة IOS البشرية الخاصة بـ Apple بشكل جيد. (يحتفظون بالحق في رفضك على القيام به اى شئ ضدهم) القسم "لا تترك برمجيا" http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/uebestpractices/uebestpractices.htmlهو دليل دقيق في كيفية علاجك في هذه الحالة.

إذا كان لديك مشكلة في منصة Apple من أي وقت مضى ، فلن تتمكن بسهولة من العثور على حل له ، استشر HIG. من المحتمل أن Apple لا تريدك ببساطة أن تفعل ذلك وعادة ما تكون (لست Apple ، لذا لا يمكنني ضمان دائمًا) لا تقول ذلك في وثائقها.

لا يمكننا الإقلاع عن التطبيق باستخدام exit(0), abort() وظائف ، لأن Apple تثبط بشدة استخدام هذه الوظائف. على الرغم من أنه يمكنك استخدام هذه الوظائف لتطوير أو اختبار الغرض.

إذا كان من الضروري أثناء التطوير أو الاختبار أنه من الضروري إنهاء التطبيق الخاص بك ، أو يوصى بتأكيد الماكرو

الرجاء العثور على هذه التفاح سؤال وجواب موضوع للحصول على مزيد من المعلومات.

باستخدام هذه الوظيفة ، خلق انطباع مثل التطبيق. لذلك تلقيت بعض الاقتراحات مثل يمكننا عرض تنبيه مع رسالة إنهاء لإدراك المستخدم حول إغلاق التطبيق ، بسبب عدم توفر وظائف معينة.

لكن IOS Human Interface Guideline for تطبيق بدء وإيقاف, ، يقترح ذلك لا تستخدم زر الإقلاع أو الإغلاق لإنهاء التطبيق. بدلاً من ذلك ، يقترحون عرض رسالة مناسبة لشرح الموقف.

لا يعرض تطبيق iOS خيارًا عن قرب أو إنهاء. يتوقف الأشخاص عن استخدام تطبيق عند التبديل إلى تطبيق آخر ، أو العودة إلى الشاشة الرئيسية ، أو وضع أجهزتهم في وضع السكون.

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

بالإضافة إلى ما سبق ، جيد ، أجب أردت فقط إضافته ، فكر في تنظيف ذاكرتك.

بعد خروج التطبيق الخاص بك ، سيقوم نظام التشغيل iPhone بتنظيف أي شيء تركه تطبيقك خلفًا ، لذلك يمكن لتحرير جميع الذاكرة يدويًا زيادة مقدار الوقت الذي يستغرقه تطبيقك للخروج.

HM ، قد تضطر إلى "ترك التطبيق إذا ، على سبيل المثال ، يتطلب تطبيقك اتصال بالإنترنت. يمكنك عرض تنبيه ثم تفعل شيئًا كهذا:

if ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
    [[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
    kill(getpid(), SIGINT); 
}
- (IBAction)logOutButton:(id)sender
{
   //show confirmation message to user
   CustomAlert* alert = [[CustomAlert alloc] initWithTitle:@"Confirmation" message:@"Do you want  to exit?" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
   alert.style = AlertStyleWhite;
   [alert setFontName:@"Helvetica" fontColor:[UIColor blackColor] fontShadowColor:[UIColor clearColor]];
   [alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{

   if (buttonIndex != 0)  // 0 == the cancel button
   {
      //home button press programmatically
      UIApplication *app = [UIApplication sharedApplication];
      [app performSelector:@selector(suspend)];
      //wait 2 seconds while app is going background
      [NSThread sleepForTimeInterval:2.0];
      //exit app when app is in background
      NSLog(@"exit(0)");
      exit(0);
  }
}

لقد استخدمت النهج [[nsmutablearray new] AddObject: NIL] المذكورة أعلاه لإلغاء التطبيق (Crash) للتطبيق دون إجراء استدعاء دالة خروج (0).

لماذا ا؟ نظرًا لأن تطبيقي يستخدم تثبيت الشهادة على جميع مكالمات API للشبكة لمنع هجمات Man-in-Middle. وتشمل هذه مكالمات التهيئة التي يجعل تطبيقي المالي على بدء التشغيل.

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

لذلك ، في هذه الحالة ، اعتبرنا أنه من الأفضل أن تبرز تنبيهًا لإبلاغ المستخدم بأن التطبيق يعمل في بيئة غير آمنة ، وبعد ذلك ، عندما يضربون "إغلاق" ، تركت القوة التطبيق باستخدام الطريقة المذكورة أعلاه.

[[UIApplication sharedApplication] terminateWithSuccess];

لقد عملت بشكل جيد ومكالمات تلقائيًا

- (void)applicationWillTerminateUIApplication *)application delegate.

لإزالة التحذير الزمني التجميع ، أضف هذا الرمز

@interface UIApplication(MyExtras)
  - (void)terminateWithSuccess;
@end 

يجب أن يقرر المستخدم متى يخرج التطبيق. لا أعتقد أنه تفاعل جيد للمستخدم عندما يتوقف التطبيق. لذلك لا يوجد واجهة برمجة تطبيقات لطيفة لذلك ، فقط زر المنزل يحتوي على واحد.

إذا كان هناك خطأ: قم بتنفيذه بشكل أفضل أو إخطار المستخدم. إذا كان يجب أن يكون هناك إعادة تشغيل: قم بتنفيذها بشكل أفضل لإخطار المستخدم.

هذا يبدو غبيًا ، لكن من الممارسات السيئة الخروج من التطبيق دون السماح للمستخدم بتقرير وعدم إخطاره. ونظرًا لأن هناك زر الصفحة الرئيسية لتفاعل المستخدم ، كما تقول Apple ، يجب ألا يكون هناك شيئان لنفس الوظيفة (الخروج من التطبيق).

الخروج من التطبيق بطريقة أخرى غير زر الصفحة الرئيسية حقا غير IOS-esque يقترب.

لقد فعلت هذا المساعد ، على الرغم من ذلك ، لا يستخدم أي أشياء خاصة:

void crash()
{ [[NSMutableArray new] addObject:NSStringFromClass(nil)]; }

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

سريع 4.2 (أو أكبر)

مكتبة تسمى Darvin من الممكن استخدامه.

import Darwin

exit(0) // Here you go

NB: هذا لم يتم إعادة تنظيمه في تطبيقات iOS.

القيام بذلك سوف يجعلك تحطم سجل.

يجب ألا تتصل مباشرة بالوظيفة exit(0) نظرًا لأنه سيترك التطبيق على الفور وسيبدو وكأن تطبيقك قد تحطم. من الأفضل أن تُظهر للمستخدمين تنبيهًا للتأكيد ودعهم يفعلون ذلك بأنفسهم.

سريع 4.2

func askForQuit(_ completion:@escaping (_ canQuit: Bool) -> Void) {
    let alert = UIAlertController(title: "Confirmation!", message: "Do you want to quit the application", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(true)
    }))
    alert.addAction(UIAlertAction(title: "No", style: UIAlertAction.Style.cancel, handler: { (action) in
        alert.dismiss(animated: true, completion: nil)
        completion(false)
    }))
    self.present(alert, animated: true, completion: nil)
}

/// Will quit the application with animation
func quit() {
    UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
    /// Sleep for a while to let the app goes in background
    sleep(2)
    exit(0)
}

الاستخدام:

self.askForQuit { (canQuit) in
     if canQuit {
         self.quit()
     }
}

الخروج من التطبيق بطريقة أخرى

لقد فعلت هذا المساعد ، على الرغم من ذلك ، لا يستخدم أي أشياء خاصة:

الخروج (0) ؛

قد يكون من المناسب الخروج من أحد التطبيقات إذا كان تطبيقًا طويل الأمد ويتم تنفيذه أيضًا في الخلفية، على سبيل المثال للحصول على تحديثات الموقع (باستخدام تحديثات الموقع القدرة الخلفية لذلك).

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

يمكن تحقيق ذلك (على الرغم من أنه لا ينبغي أن يكون كذلك، انظر أدناه :-) من خلال شيء مثل:

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
        exit(0);
    } else {
       // normal handling.
    }
}

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

ومع ذلك، سيكون من الأفضل استخدام نهج أكثر معيارية لإعلام النظام بإمكانية إنهاء التطبيق.على سبيل المثال، في هذه الحالة، من خلال التأكد من عدم استخدام نظام تحديد المواقع العالمي (GPS) عن طريق إيقاف طلب تحديثات الموقع، بما في ذلك إيقاف تشغيل عرض الموقع الحالي على عرض الخريطة إذا كان موجودًا.وبهذه الطريقة، سيهتم النظام بإنهاء التطبيق لبضع دقائق (على سبيل المثال. [[UIApplication sharedApplication] backgroundTimeRemaining]) بعد أن يدخل التطبيق في الخلفية.سيحصل هذا على نفس الفوائد دون الحاجة إلى استخدام التعليمات البرمجية لإنهاء التطبيق.

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    if (/* logged out */) {
       // stop requesting location updates if not already done so
       // tidy up as app will soon be terminated (run a background task using beginBackgroundTaskWithExpirationHandler if needed).
    } else {
       // normal handling.
    }
}

وبالطبع باستخدام exit(0) لن يكون مناسبًا أبدًا لتطبيق الإنتاج المتوسط ​​الذي يتم تشغيله في المقدمة، وفقًا للإجابات الأخرى التي تشير إلى ذلك http://developer.apple.com/iphone/library/qa/qa2008/qa1561.html

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top