Frage

Ich habe versucht, mit dieser für eine lange Zeit zu spielen, um und ich kann nicht scheinen, um die beste Lösung zu finden. Ich bin immer verwirrt, weil es zu sein scheint unterschiedliche Antworten / Meinungen darüber, wie diese scheinbar einfache Aufgabe zu erfüllen.

Ich möchte eine wiederverwendbare Klasse zu müssen in der Lage genannt ActivityIndicatorController. Dieser Regler hat zwei Hauptmethoden: activateIndicator und deactivateIndicator. Es dauert eine UIView als Argument / Immobilien sowie ein NSString für ein Label. Nach der Aktivierung wird die Benutzerinteraktion in der UIView auszuschalten und ein Rechteck subview hinzu (mit alpha und abgerundeten Ecken), eine UIActivityIndicator Steuerung und eine UILabel für den Statustext. Dies ist wünschenswert, weil auf diese Weise habe ich nicht benutzerdefinierte UIActivityIndicatorView Code in jedem View-Controller haben oder um eine ActivityIndicator in jedem NIB zu haben einzurichten.

Das Problem, das ich im Grunde habe, ist, wie dieser Prozess zu beginnen, um hinzuzufügen und die ActivityIndicator Animieren. Einige Methoden, die ich versucht habe, nicht angezeigt, die neue Ansicht überhaupt. Andere Arbeit, aber der ActivityIndicator nicht belebter.

Ich habe versucht, mit [NSThread detachNewThreadSelector: @selector (startAnimating) toTarget: activityIndicator withobject: nil]. In der activateIndicator Methode, aber das ist nicht das neue UIView nicht angezeigt

Ich habe versucht, mit [NSThread detachNewThreadSelector: @selector (activateIndicator) toTarget: activityIndicatorController withobject: nil]. Von einem Aufruf der Methode, aber das die ganze Schöpfung des neuen UIView in einem separaten Thread setzen würde

Nun zur Frage:

Teil 1: Ich verstehe, dass alle UI auf dem Haupt-Thread behandelt werden sollen, ist das richtig

?

Teil 2: Was ist der Unterschied / Vorteil / Nachteil der Verwendung von [NSThread detachThreadSelector] gegen NSOperation

Teil 3: Ist es besser, zu:

(a) mit einem Rückruf an den Haupt-Thread die langwierige Operation zu einem neuen Hintergrund-Thread senden oder zu

(b) die UIActivityIndicatorView startAnimating Verfahren auf einen separaten Thread senden und den langwierigen Prozess auf dem Haupt-Thread ausgeführt

und warum?

Hier ist mein aktueller Code:

ActivityViewController Klasse:

-(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];
}

Aufrufe von Code aus mehreren Stellen in der App:

    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;
War es hilfreich?

Lösung

  

Teil 1: Ich verstehe, dass alle UI auf dem Haupt-Thread behandelt werden sollen, ist das richtig

?

Richtig.

  

Teil 2: Was ist der Unterschied / Vorteil / Nachteil der Verwendung von [NSThread detachThreadSelector] gegen NSOperation

NSOperation ist eine übergeordnete Schnittstelle, die Sie Operationen anstehen, erstellen mehrere Operationen erlaubt, die voneinander abhängig sind, usw. Weitere Möglichkeiten zur Arbeit mit Aufgaben im Hintergrund sind performSelectorOnMainThread:... / performSelectorInBackground:... und Grand Central Dispatch.

  

Teil 3: Ist es besser, zu:

     

(a) mit einem Rückruf an den Haupt-Thread die langwierige Operation zu einem neuen Hintergrund-Thread senden oder zu

     

(b) die UIActivityIndicatorView startAnimating Verfahren auf einen separaten Thread senden und den langwierigen Prozess auf dem Haupt-Thread ausgeführt

Aufgrund der Antwort auf Frage 1 (a) ist Ihre einzige Option.

Andere Tipps

Setzen Sie Ihre langwierige Arbeit in einem separaten Thread, auf diese Weise nicht vollständig die UI in Fall nicht blockieren Sie eine Interaktion tun müssen (sagen den Vorgang abzubrechen). Dann Ihre ActivityIndicatorController zu dem Haupt-Thread ausrufen sollten all UI Dinge zu tun, z.

@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.

Sobald angezeigt und animiert, wird die Aktivitätsanzeige weiterhin auch den Haupt-Thread Animieren blockiert wird.

Allerdings hat die Ansicht keine Chance zu kommen, weil die Laufschleife noch zu ausgeführt, da fehlt noch längerer Betrieb.

Also ich denke, was Sie brauchen, ist nur performSelector:withObject:afterDelay mit Verzögerung 0, so dass Ihr langer Betrieb der Warteschlange werden und durchgeführt, nachdem Ihre Anzeige sichtbar werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top