Zuerst sollten Sie nicht nur erstellen und dann die Warteschlange freigeben. Es ist natürlicher, diese Warteschlange als eine der Klassen Ihrer Klasse zu erstellen und sie dann zu veröffentlichen, wenn der View-Controller nicht mehr aktiv ist (Sie können auch ausstehende Operationen abbrechen und alle laufenden Operationen abbrechen/warten).
Zweitens benötigen Sie den Autorelease-Pool in der Methode, die die Operation erstellt und in der Warteschlange hinzufügt, seit diese Methode aus dem Hauptthread aufgerufen wird. Stattdessen benötigen Sie den Autorelease-Pool aus der Methode, die Ihr Objekt tatsächlich aufruft (dies könnte in einem anderen Thread ausgeführt werden).
Also, haben Sie vielleicht die folgende (vorausgesetzt, Sie Ihre Warteschlange Ivar warteschlange_ nennen):
- (void)viewDidLoad
{
[super viewDidLoad];
if(!queue_) queue_ = [[NSOperationQueue alloc] init];
// other view loading code
}
- (void)loadData
{
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(firstRun) object:nil];
[queue_ addOperation:operation];
[operation release];
}
- (void)firstRun
{
// Here we may run on another thread, so 1) we need an autorelease pool; and
// 2) we need to make sure we don't do anything that requires a runloop
NSAutoreleasePool* threadPool = [NSAutoreleasePool new];
// do long-running things
[threadPool drain];
}
- (void)dealloc
{
if(queue_) {
[queue_ setSuspended:YES];
[queue_ cancelAllOperations];
// you need to decide if you need to handle running operations
// reasonably, but don't wait here because that may block the
// main thread
[queue_ release];
}
// other dealloc stuff
[super dealloc];
}
Sie können auch Ihre Warteschlange auf Nachfrage, initialisieren so statt in viewDidLoad der Initialisierung überprüfen für seine Existenz und initialisieren Falls nötig, fügen Sie eine Operation hinzu. Dies könnte in einen eigenen Methodenaufruf eingebettet sein, aber eine lazy Initialisierung hier ist wahrscheinlich nicht wirklich notwendig, da Warteschlangen ziemlich leicht sind.
danke Jason, werden irgendwelche Methoden nach dem threadpool init automatisch verwendet werden? Außerdem muss ich den Threadpool freigeben. Ich sehe, dass es mit neuem begonnen hat. – zambono
@zambono: Ja, es sollte die erste Zeile sein und Sie sollten den Pool als letzte Zeile in Ihrer Methode entleeren. Die "neue" Methode ist nur eine Abkürzung für alloc/init, also ist [NSObject new] dasselbe wie [[NSObject alloc] init], also sind Sie dafür verantwortlich. Autorelease-Pools sind jedoch etwas Besonderes. Die Drain-Methode dort gibt auch den Pool frei, so dass Sie nicht eine bestimmte Release-Nachricht senden müssen (wenn Sie dies tun, ignoriert es es einfach). –