سؤال

أحاول عرض UialertView في معالج استثناء iPhone على مستوى أعلى. تبدو وظيفة المعالج هكذا:

void applicationExceptionHandler(NSException *ex) {
  UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
                                                      message:[ex reason]
                                                      delegate:nil
                                             cancelButtonTitle:@"OK"
                                             otherButtonTitles:nil];
  [alertView show];
}

لقد رأيت رمزًا مشابهًا في مكان آخر (على سبيل المثال ، NSSetUncaughtexceptionHandler لا تصطاد جميع الأخطاء على iPhone).

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

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

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

المحلول

لا أعرف بالضبط كيف [alertView show] تم تنفيذه ، لكنني أتخيل أنه يجري بعض التغييرات على التسلسل الهرمي للعرض ثم يعرض نفسه لعرض التنبيه على الممر التالي عبر حلقة التشغيل (ابحث NSRunLoop).

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

إذا قمت بتضمين [[NSRunLoop currentRunLoop] run] في نهاية معالج الاستثناء الخاص بك ، قد يظهر التنبيه.

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

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

نصائح أخرى

شكرًا لك على Benzado ، إليك ما أعتقد أنه معالج استثناء عام رائع. أنا مبتدئ ، آمل أن يتم ذلك بشكل صحيح ، لكنه يعمل :)

في ... appdelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{        
    [window makeKeyAndVisible];

    NSSetUncaughtExceptionHandler(&exceptionHandler);

    return YES;
}

BOOL exceptionAlertDismissed = FALSE;
void exceptionHandler(NSException *exception)
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"App Committed Suicide"
        message:@"Oh dear, that wasn't supposed to happen. You will have to restart the application... sorry!"
        delegate:[[UIApplication sharedApplication] delegate] cancelButtonTitle:nil otherButtonTitles:@"That's ok!", @"Erm, bye...", nil];
    [alert show];
    [alert release];

    while (exceptionAlertDismissed == FALSE)
    {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    exceptionAlertDismissed = TRUE;
}

وفي ... appdelegate.h:

@interface ...appDelegate : NSObject <UIApplicationDelegate, UIAlertViewDelegate>
...
void exceptionHandler(NSException *exception);

يجب عليك التحقق مما إذا تم الوصول إلى الرمز أو إذا كان لديك مشكلة عرض فقط.

سوف NSLOG توضح ذلك.

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

[self performSelector: @selector(showAlert:) withObject:@"msg" afterDelay: 0.1];

إذا كنت تصل إلى ذلك ، فإن سياق التنفيذ ليس مشكلة ولكنك ببساطة لا ترى تنبيهًا ، فقد لا يكون [ALERT Show] أعلى مستوى. في مثل هذه الحالة ، قد تحتاج إلى إعادة توجيه رسالة عبر ShowInview على سبيل المثال مع ActionSheet:

topDelegate=[[UIApplication sharedApplication] delegate];
topDelegateWindow=[topDelegate.window.subviews objectAtIndex:0];

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