6 Stimmen

Verhinderung einer Warnung, wenn eine NSDocument-Datei programmatisch umbenannt wird

Meine Anwendung ermöglicht es dem Benutzer, Dokumente, die gerade geöffnet sind, umzubenennen. Dies ist trivial, und funktioniert gut, mit einem wirklich ärgerlich Fehler, den ich nicht herausfinden kann. Wenn eine Datei umbenannt wird, warnt AppKit (freundlicherweise) den Benutzer das nächste Mal, wenn sie versuchen, das Dokument zu speichern. Der Benutzer sagt "OK" und alles läuft normal weiter. Das macht Sinn, wenn etwas außerhalb der Anwendung das Dokument geändert hat, aber nicht, wenn es tatsächlich durch das Dokument selbst gemacht wurde.

Der Code sieht ungefähr so aus:

-(void)renameDocumentTo:(NSString *)newName {
  NSURL *newURL = [[[self fileURL] URLByDeletingLastPathComponent]
                                   URLByAppendingPathComponent:newName];

  NSFileManager *fileManager = [NSFileManager defaultManager];
  [fileManager moveItemAtURL:[self fileURL] toURL:newURL];
  NSDictionary *attrs = [fileManager attributesForItemAtPath:[newURL path] error:NULL];

  [self setFileURL:newURL];
  [self setFileModificationDate:[attrs fileModificationDate]];
}

Man sollte meinen, dass das ausdrückliche Setzen der neuen URL und des Änderungsdatums auf dem Dokument ausreichen würde, aber leider ist das nicht der Fall. Cocoa erzeugt immer noch die Warnung.

Ich habe versucht, die Reihenfolge zu ändern (die neue URL auf das Dokument zu setzen, DANN die Datei umzubenennen), aber das hilft nicht.

Ich habe auch eine Lösung ausprobiert, die von einem Benutzer in einem alten Beitrag bei CocoaDev vorgeschlagen wurde:

[self performSelector:@selector(_resetMoveAndRenameSensing)];

Aber auch das hält die Warnung nicht auf, und ich vermute, dass es hat eine geeignete Methode zu sein, dies mit der dokumentierten API zu tun. Wie geht Xcode damit um, wenn ein Benutzer auf eine Datei in der Projektstruktur klickt und sie in etwas anderes umbenennt. Es warnt den Benutzer nicht über die Umbenennung, da der Benutzer tatsächlich die Umbenennung durchgeführt.

Was muss ich tun?

3voto

Mike Abdullah Punkte 14832

In den Hauptdokumenten ist nicht viel darüber zu finden. Werfen Sie stattdessen einen Blick in die 10.5 Release Notes: http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html%23X10_5Notes unter der Überschrift "NSDocument Checking for Modified Files At Saving Time"

(Im Fall von Xcode hat es eine lange Geschichte und es würde mich nicht wundern, wenn es nicht mit NSDocument für Dateien innerhalb des Projekts)

Es ist erwähnenswert, dass das Verschieben einer Datei ihr Änderungsdatum nicht ändert, so dass der Aufruf von -setFileModificationDate: wird wahrscheinlich keine Auswirkungen haben.

Eine Möglichkeit wäre also die Umgehung NSDocument die übliche Warnung wie folgt:

- (void)saveDocument:(id)sender;
{
    if (wasRenamed)
    {
        [self saveToURL:[self fileURL] ofType:[self fileType] forSaveOperation:NSSaveOperation delegate:nil didSaveSelector:nil contextInfo:NULL];
        wasRenamed = NO;
    }
    else
    {
        [super saveDocument:sender];
    }
}

Idealerweise sollten Sie auch prüfen, ob die Möglichkeit besteht:

  1. App bitten, das Dokument umzubenennen
  2. Umbenannte Datei wird dann von einer anderen Anwendung geändert/verschoben
  3. Benutzer geht zum Speichern des Dokuments

Zu diesem Zeitpunkt sollten Sie das übliche Warnblatt einblenden lassen. Könnte wahrscheinlich durch etwas wie erreicht werden:

- (void)renameDocumentTo:(NSString *)newName
{
    // Do the rename

    [self setFileURL:newURL];
    wasRenamed = YES; // MUST happen after -setFileURL:
}

- (void)setFileURL:(NSURL *)absoluteURL;
{
    if (![absoluteURL isEqual:[self fileURL]]) wasRenamed = NO;
    [super setFileURL:absoluteURL];
}

- (void)setFileModificationDate:(NSDate *)modificationDate;
{
    if (![modificationDate isEqualToDate:[self fileModificationDate]]) wasRenamed = NO;
    [super setFileModificationDate:modificationDate];
}

Andernfalls ist die einzige andere Möglichkeit, die ich sehe, eine der Standard-Speicher-/Schreibmethoden mit einigen benutzerdefinierten Parametern aufzurufen, die Ihre Dokument-Unterklasse auffordern, das aktuelle Dokument zu verschieben, anstatt es tatsächlich zu speichern. Ich denke, das wäre schwieriger. Vielleicht definieren Sie Ihre eigene NSSaveOperationType ?

Mit dieser Technik sollte das Dokumentsystem verstehen, dass die Umbenennung Teil eines speicherähnlichen Vorgangs war, aber man müsste schon ein wenig experimentieren, um sicher zu sein.

1voto

Alessandro Punkte 91

Inspiriert von der Antwort von @Mike, habe ich die "moved to"-Meldung durch Umleitung nicht mehr angezeigt bekommen NSSaveOperation a NSSaveAsOperation . In meiner Unterklasse NSDocument:

  • I Überlastung saveDocumentWithDelegate:didSaveSelector:contextInfo: um die Speicher-URL und den Dokumenttyp zu bestimmen (indem Sie diese der self ); wenn die alte fileURL existiert, verschiebe ich sie an den neuen Ort
  • Innerhalb saveDocumentWithDelegate:didSaveSelector:contextInfo: Ich leite den Anruf um an [self saveToURL:self.fileURL ofType:self.fileType forSaveOperation:NSSaveAsOperation completionHandler: ...] anstelle von [super saveDocumentWithDelegate:didSaveSelector:contextInfo:]

Das funktioniert bei mir.

0voto

stackr Punkte 2724

Ist es nicht möglich, die Frage für den Benutzer programmatisch zu beantworten? Oder Sie können sofort nach der Umbenennung speichern, so dass der Benutzer alle Antworten in einem Rutsch erhält.

Wie ich sehe, besteht dieses Problem schon seit einiger Zeit, weshalb ich Sie darauf hinweise, die Referenz wird wohl nichts nützen

Ich hoffe, ich konnte ein wenig helfen, auch wenn es Ihr Problem nicht direkt löst.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X