ما هي أفضل طريقة للتعامل مع UiActivityIndicator ومواضيع متعددة؟

StackOverflow https://stackoverflow.com/questions/4247533

سؤال

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

أريد أن أكون قادرًا على الحصول على فئة قابلة لإعادة الاستخدام تسمى ActivityIndicatorController. تحتوي وحدة التحكم هذه على طريقتان رئيسيتان: ActivateIndicator و DeactivativeIndicator. يستغرق UIVIEW كوسيطة/خاصية بالإضافة إلى NSSTRING لتسمية. عند التنشيط ، سيتم إيقاف تفاعل المستخدم في UIVIEW وإضافة عرض مستطيل (مع زوايا ألفا وزوايا مدورة) ، وعنصر تحكم UiActivityIndicator و uilabel لنص الحالة. هذا أمر مرغوب فيه لأنه بهذه الطريقة لا يجب أن يكون لدي رمز مخصص UiActivityIndicatorView في كل وحدة تحكم عرض أو أن أضطر إلى إعداد ActivityIndicator في كل NIB.

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

لقد حاولت استخدام [nsThread dutachnewThreadSelector:@selector (startAnimating) totarget: ActivityIndicator withObject: nil] داخل طريقة ActivateIndicator ، ولكن هذا لا يعرض Uiview الجديد.

لقد حاولت استخدام [nsThread dutachnewThreadSelector:@selector (ActivateIndicator) totarget: ActivityIndicatorController withObject: nil] من طريقة الاتصال ، ولكن هذا من شأنه أن يضع إنشاء UiView بالكامل في موضوع منفصل.

الآن إلى السؤال:

الجزء 1: أفهم أنه يجب التعامل مع جميع واجهة المستخدم على الخيط الرئيسي ، هل هذا صحيح؟

الجزء 2: ما هو الفرق/ميزة/عيب استخدام [nsThread detachThreadSelector] مقابل nsoperation؟

الجزء 3: هل من الأفضل أن:

(أ) إرسال العملية الطويلة إلى سلسلة خلفية جديدة مع رد اتصال إلى الخيط الرئيسي أو

)

و لماذا؟

هنا هو قانون بلدي الحالي:

فئة ActiveViewController:

-(void)activateIndicator {
NSLog(@"activateIndicator called");
if (isActivated || !delegateView)
    return;
NSLog(@"activateIndicator started");

[delegateView.view setUserInteractionEnabled:NO];
[delegateView.navigationController.view setUserInteractionEnabled:NO];
[delegateView.tabBarController.view setUserInteractionEnabled:NO];

float w = [[UIScreen mainScreen] bounds].size.width;
float h = [[UIScreen mainScreen] bounds].size.height;

NSLog(@"Width = %f\nHeight = %f", w, h);

if (!disabledView) {
    disabledView = [[[UIView alloc] initWithFrame:CGRectMake((w - kNormalWidth) / 2.0, (h - kNormalHeight) / 2.0, kNormalWidth, kNormalHeight)] autorelease];
    disabledView.center = [[[delegateView.view superview] superview] center];
    [disabledView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.85]];

CALayer *layer = [disabledView layer];
NSLog(@"layer=%@",layer);
NSLog(@"delegate=%@",[layer delegate]);
layer.cornerRadius = 12.0f;
}

if (!activityIndicator) {
    activityIndicator = [[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(kNormalWidth / 2, 10.0f, 40.0f, 40.0f)] autorelease];
    [activityIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
    activityIndicator.center = disabledView.center;
}

if (!activityLabel) {
    activityLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10.0f, 100.0f, kNormalWidth - 20, 38)] autorelease];
    activityLabel.text = labelText;
    activityLabel.textAlignment = UITextAlignmentCenter;
    activityLabel.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
    activityLabel.textColor = [UIColor colorWithWhite:1.0f alpha:1.0f];
    activityLabel.center = disabledView.center;
}

[[[delegateView.view superview] superview] addSubview:disabledView];

[[[delegateView.view superview] superview] addSubview:activityIndicator];
[[[delegateView.view superview] superview] addSubview:activityLabel];


[NSThread detachNewThreadSelector:@selector(startAnimating) toTarget:activityIndicator withObject:nil];
}

استدعاء رمز من أماكن متعددة في التطبيق:

    ActivityIndicatorController *aic = [[ActivityIndicatorController alloc] init];
aic.delegateView = self;
aic.labelText = @"Test...";
[aic activateIndicator];

//DO LENGTHY WORK ON MAIN THREAD

[aic deactivateIndicator];
[aic release], aic = nil;
هل كانت مفيدة؟

المحلول

الجزء 1: أفهم أنه يجب التعامل مع جميع واجهة المستخدم على الخيط الرئيسي ، هل هذا صحيح؟

صيح.

الجزء 2: ما هو الفرق/ميزة/عيب استخدام [nsThread detachThreadSelector] مقابل nsoperation؟

NSOperation هي واجهة عالية المستوى تتيح لك قائمة انتظار عمليات الانتظار ، وإنشاء العديد من العمليات التي تعتمد على بعضها البعض ، وما إلى ذلك. الخيارات الأخرى للعمل مع المهام في الخلفية performSelectorOnMainThread:.../performSelectorInBackground:... و Grand Central Dispatch.

الجزء 3: هل من الأفضل أن:

(أ) إرسال العملية الطويلة إلى سلسلة خلفية جديدة مع رد اتصال إلى الخيط الرئيسي أو

)

بسبب الإجابة على السؤال 1 ، (أ) هو خيارك الوحيد.

نصائح أخرى

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

@implementation ActivityIndicatorController

    - (void)activateIndicator
    {
        [self performSelectorOnMainThread:@selector(activateOnMainThread)
                               withObject:nil
                            waitUntilDone:YES];
    }

    - (void)activateOnMainThread
    {
        // Do your actual UI stuff here.
    }

    // And similarly for the deactivate method.

بمجرد عرضه والرسوم المتحركة ، سيستمر مؤشر النشاط حتى يتم حظر الخيط الرئيسي.

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

لذلك أعتقد أن ما تحتاجه هو فقط performSelector:withObject:afterDelay مع التأخير 0 ، لذلك سيتم قائمة التشغيل الطويل الخاص بك وتنفيذها بعد أن أصبح مؤشرك مرئيًا.

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