سؤال

لدي طريقة تنشر بيانات HTTP وتعرض UialertView إذا كان هناك خطأ. إذا كان لدي العديد من منشور HTTP ، فسوف أعرض عدة uialertview لكل خطأ.

أريد أن أعرض uialertview فقط إذا لم يكن يعرض UialertView آخر. كيف يمكنني تحديد هذا؟

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

المحلول

على الكائن الذي يتصل بتعيين Ivar قبل استدعاء طريقة العرض على UialertView الخاص بك.

...

if (!self.alertShowing) {
    theAlert = [[UIAlertView alloc] initWithTitle:title message:details delegate:self cancelButtonTitle:nil otherButtonTitles:@"Okay", nil];
    self.alertShowing = YES;
    [theAlert show];
}

...

ثم في طريقة المندوب الخاصة بك للتنبيه ، قم بإدارة إعداد العلم IVAR إلى NO:

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
  ...
      self.alertShowing = NO;
}

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

نصائح أخرى

لماذا لا تحقق فقط من الخاصية المرئية ، التي تحتفظ بها فئة UialertView؟

if (_alert) //alert is a retained property
{
    self.alert = [[[UIAlertView alloc] initWithTitle:@"Your Title"
                                             message:@"Your message" 
                                            delegate:self
                                   cancelButtonTitle:@"Cancel"
                                   otherButtonTitles:@"OK"] autorelease];
}
if (!_alert.visible)
{
    [_alert show];
}

إذا كنت تستطيع التحكم في طرق عرض التنبيه الأخرى ، تحقق من visible خاصية لكل منهم.


في iOS 6 أو قبل ، عندما يظهر تنبيه ، سيتم نقله إلى _uialertoverlaywindow. لذلك ، تتمثل الطريقة الهشة للغاية في التكرار من خلال جميع النوافذ والتحقق مما إذا كان هناك أي عرض فرعي لـ UialertView.

for (UIWindow* window in [UIApplication sharedApplication].windows) {
  NSArray* subviews = window.subviews;
  if ([subviews count] > 0)
    if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
      return YES;
}
return NO;

هذا غير موثق لأنه يعتمد على التسلسل الهرمي للمساواة الداخلية ، على الرغم من أن Apple لا يمكنها أن تشكو من هذا. طريقة أكثر موثوقية ولكن أكثر غير موثقة هي التحقق إذا [_UIAlertManager visibleAlert] لا شيء.

لا يمكن لهذه الطرق التحقق مما إذا تم عرض UialertView من Spishboard.

- (BOOL)checkAlertExist {
    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        NSArray* subviews = window.subviews;
        if ([subviews count] > 0) {
            for (id cc in subviews) {
                if ([cc isKindOfClass:[UIAlertView class]]) {
                    return YES;
                }
            }
        }
    }
    return NO;
}

خيار آخر يعمل عبر التطبيق بأكمله ولا يتضمن المشي في مكدس العرض هو الفئة الفرعية UIAlertView إلى MyUIAlertView, ، أضف متغيرًا ثابتًا (فئة) BOOL alertIsShowing, وتجاوز -(void)show المحدد.

في تجاوزك show المحدد ، تحقق alertIsShowing عامل. إذا كان YES ثم حاول مرة أخرى بعد التأخير (استخدم dispatch_after أو تعيين NSTimer). إذا كان NO, ، انطلق واتصل [super show] وتعيين YES إلى alertIsShowing; ؛ عندما يتم إخفاء عرض التنبيه ، قم بتعيين alertIsShowing ارجع الى NO (ستحتاج إلى أن تكون ذكيًا بشأن التعامل مع المندوب).

أخيرًا ، تمر واستبدل كل شيء UIAlertView حالات مع MyUIAlertView.

أعتقد أنه سيعمل:

-(BOOL) doesAlertViewExist {
    if ([[UIApplication sharedApplication].keyWindow isMemberOfClass:[UIWindow class]])
    {
        return NO;//AlertView does not exist on current window
    }
    return YES;//AlertView exist on current window
}

سويفت:

func showAlert(withTitle title: String, message: String, viewController: UIViewController) {
    if viewController.presentedViewController == nil { // Prevent multiple alerts at the same time
        let localizedTitle = NSLocalizedString(title, comment: "")
        let localizedMessage = NSLocalizedString(message, comment: "")
        let alert = UIAlertController(title: localizedTitle, message: localizedMessage, preferredStyle: .Alert)
        let action = UIAlertAction(title: "OK", style: .Default, handler: nil)
        alert.addAction(action)

        viewController.presentViewController(alert, animated: true, completion: nil)
    }
}
// initialize default flag for alert... If alert is not open set isOpenAlert as NO
BOOL isAlertOpen;
isAlertOpen = NO;
if (isAlertOpen == NO) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"Alert is Open" delegate:self cancelButtonTitle:@"Okay!!" otherButtonTitles: nil];
    [alert show];
    // Now set isAlertOpen to YES
    isAlertOpen = YES;
}
else
{
    //Do something
}
+ (BOOL)checkAlertExist {

    for (UIWindow* window in [UIApplication sharedApplication].windows) {
        if ([window.rootViewController.presentedViewController isKindOfClass:[UIAlertController class]]) {
            return YES;
        }
    }
    return NO;
}

بعض الملاحظات حول سعيي للعثور على uialertview في العرض الهرمي:

حاولت حلقة من خلال كل من [UIApplication sharedApplication].windows عرض بشكل متكرر ولكن لم يستطع العثور على أي شيء.

ال windows ممتلكات UIApplication تنص المستندات على ما يلي:

تحتوي هذه الخاصية على كائنات UiWindow المرتبطة حاليًا بالتطبيق. لا تتضمن هذه القائمة Windows التي تم إنشاؤها وإدارتها بواسطة النظام, ، مثل النافذة المستخدمة لعرض شريط الحالة.

لذلك هذا جعلني أدرك أن UIWindow أين UIAlertView يمكن أن يكون موجودًا حتى لا يتم تقديمه إلينا.

ومع ذلك ، هناك أيضًا خاصية UIApplication اتصل keyWindow. عند الحلق من خلال ذلك ، وجدت فصولًا خاصة من شأنها أن تشكل منظرًا تنبيهًا:

على iOS 7: _UIModalItemHostingWindow, _UIModalItemAlertContentView, _UIBackdropEffectView إلخ.

على iOS 8: _UIAlertControllerActionView, _UIAlertControllerShadowedScrollView, _UIBackdropView إلخ.

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

للأشخاص الذين يستخدمون ، الأحدث ، UIAlertController يمكن أن تحصل على الإشارة إليها باستخدام IOS 8 باستخدام:[UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController.

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