2016-03-25 10 views
0

Ich verwende eine UIDocument-Unterklasse, die die Möglichkeit hat, ihre saveToURL-Methode aus mehr als einem Thread aufgerufen. Ich habe eingekapselt es daher in einer Wrapper-Funktion, die ich Thread-sicher machen will:Verwendung von @ synchronized mit synchronen Operationen

- (void)saveWithCompletionBlock:(void(^)(TransactionDocumentReturnCode status))completion { 
    @synchronized (self) { 
     [self saveToURL:[self fileURL] forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success){ 
      // Generate returncode depending on outcome of save operation 
      completion(returncode); 
     }]; 
    } 
} 

Ich gehe davon aus, dass der Anruf zu [self saveToURL:...] kehrt sofort, da den Speichervorgang selbst auf einem Hintergrund-Thread auftritt, wodurch die Sperre möglicherweise vor dem Abschluss der Sicherungsoperation freigegeben werden. Also, gibt es eine Möglichkeit, andere Threads mit dem Aufruf von saveWithCompletionBlock: gesperrt zu halten, bis der Completion Block saveToURL aufgerufen wurde?

+0

Werfen Sie einen Blick auf diese Antwort für zwei Möglichkeiten, dies zu implementieren: http://Stackoverflow.com/a/7649768/78496 – chedabob

+0

Vielen Dank @chedabob. Würde die Verwendung von GCD oder NSOperationQueue dazu führen, dass die nachfolgenden Aufrufe der Sicherungswrapperfunktion blockiert werden, bis der Abschlussblock der Sicherungsoperation beendet wurde? – mashers

Antwort

0

Eine mögliche Lösung, an die ich gerade gedacht habe, ist das Hinzufügen einer Eigenschaft zu meiner UIDocument-Unterklasse, um anzuzeigen, ob eine Sicherungsoperation ausgeführt wird, und wenn ja, warten und dann erneut versuchen. Wrapping die Überprüfung und Einstellung dieser Eigenschaft in @synchronize sollten zwei Threads verhindern gleichzeitig den Wert als falsch lesen und glauben, dass sie das Dokument speichern können:

- (void)saveWithCompletionBlock:(void(^)(TransactionDocumentReturnCode status))completion { 
    @synchronized(self){ 
     if (self.isSaving) { 
      [self performSelector:@selector(saveWithCompletionBlock:) withObject:completion afterDelay:1.0]; 
      return; 
     } 

     self.isSaving = YES; 
    } 

    [self saveToURL:[self fileURL] forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success){ 
     // Generate returncode depending on outcome of save operation 
     completion(returncode); 
     self.isSaving = NO; 
    }]; 
} 

Ich weiß nicht, ob dies ausreichen würde, oder gute Multi betrachtet -Drehübung.

+0

Die obige Lösung scheint gut zu funktionieren. Das Hinzufügen eines Aufrufs zu '[NSObject cancelPreviousPerformRequestsWithTarget: self]' vor '[self performSelector: ...]' führte dazu, dass die Anwendung bis zum Ende der ersten Sicherungsoperation wartete und dann nach dem Abschluss nur noch einmal speicherte. Ich würde immer noch jede Rückmeldung zu dieser Lösung begrüßen. – mashers

Verwandte Themen