Как убедиться, что окно документов запоминает свое положение

Я использую стандартное приложение базы документов AppKit NSPersistentDocument и хотел бы, чтобы окно документа запоминало свое местоположение и открывалось в том же положении, в котором оно было закрыто в последний раз.

Обратите внимание, что установка имени автосохранения в IB в окне приведет к тому, что все документы будут открываться в одном и том же месте. Я хочу, чтобы документ запоминал свою позицию на основе имени файла документа.

Я создал подкласс NSPersistentDocument и в настоящее время задал имя автосохранения в функции windowControllerDidLoadNib:. Это почти работает нормально, за исключением того, что если я многократно открываю и закрываю один и тот же документ, не закрывая приложение, то каждый раз, когда высота его окна увеличивается на небольшую величину (26 пикселей), почти как каскадная вещь. Однако, если я полностью закрою приложение и снова открою его, документ точно запомнит свою предыдущую позицию. Я что-то не так делаю или это баг. Есть ли какая-то очистка, которую я должен сделать, чтобы убедиться, что размер окна не изменяется каждый раз, когда он снова открывается.

// NSPersistentDocument subclass

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
    LOG(@"windowControllerDidLoadNib called...");
    [super windowControllerDidLoadNib:aController];

    if ([self autoSaveName] != nil) {
        [aController setWindowFrameAutosaveName:[self autoSaveName]];
    }

    [aController setShouldCascadeWindows:NO];

}
- (NSString*)autoSaveName
{
    return [[self fileURL] lastPathComponent];
}

Если я добавлю следующий код, чтобы добавить 22 пикселя к его высоте

- (NSRect)windowPositionPreference {
    LOG(@"printUserDefaults called");

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *autosaveNameKey = [NSString stringWithFormat:@"NSWindow Frame %@", [self autoSaveName]];
    NSString *frameString = [defaults objectForKey:autosaveNameKey];
    NSArray *array = [frameString componentsSeparatedByString:@" "];
    CGFloat x = [[array objectAtIndex:0] floatValue];
    CGFloat y = [[array objectAtIndex:1] floatValue];
    CGFloat width = [[array objectAtIndex:2] floatValue];
    CGFloat height = [[array objectAtIndex:3] floatValue];

    NSRect rect = CGRectMake(x, y, width, height+22);
    FLOG(@" window frame = %fx, %fy, %fw, %fh", x, y, width, height);

    return rect;
}

а затем установите кадр так, как в - (void)windowControllerDidLoadNib:(NSWindowController *)aController

NSRect rect = [self windowPositionPreference];
    [aController.window setFrame:rect display:YES];

Позиция вроде точно сохраняется. Конечно, автосохранение просто предназначено для работы.


person Duncan Groenewald    schedule 18.10.2013    source источник


Ответы (1)


Вышеупомянутое все еще не работало, но после некоторого возни я отказался от использования автосохранения имени из-за автоматического каскадирования, которое, кажется, невозможно отключить.

Теперь я просто сохраняю свои настройки и устанавливаю рамку окна, используя приведенный ниже код. До сих пор он работал отлично, и мне не приходилось создавать собственные подклассы NSWindowController или NSWindow.

// Methods in subclassed NSPersistentDocument

- (void)windowControllerDidLoadNib:(NSWindowController *)aController {
    [aController setShouldCascadeWindows:NO];

    _mainWindow = aController.window;
    [self restoreSavedWindowPosition];

}

- (void)close {

    [self saveWindowPosition];
    [super close];

}

- (void)saveWindowPosition {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSString *autosaveNameKey = [NSString stringWithFormat:@"OSWindow Frame %@", [self autoSaveName]];

    [defaults setObject:[self stringFromFrame] forKey:autosaveNameKey];
}

- (void)restoreSavedWindowPosition {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSString *autosaveNameKey = [NSString stringWithFormat:@"OSWindow Frame %@", [self autoSaveName]];

    NSString *frameString = [defaults objectForKey:autosaveNameKey];

    // Do nothing if it has not been set
    if (frameString) {
        [_mainWindow setFrame:[self rectFromString:frameString] display:YES animate:YES];
    }
    else {
        // Set the default for new docs
        NSRect rect = CGRectMake(70, 350, 1000, 760);
        [_mainWindow setFrame:rect display:YES animate:YES];
    }

    return;
}

// Use the filename as the preferences key
- (NSString*)autoSaveName {

    return [[self fileURL] lastPathComponent];

}

- (NSString *)stringFromFrame {
    NSRect rect = _mainWindow.frame;
    rect.origin.y = rect.origin.y + 26;
    rect.size.height = rect.size.height - 26;

    return [self stringFromRect:rect];
}

- (NSString *)stringFromRect:(NSRect)rect {
    return [NSString stringWithFormat:@"%f %f %f %f", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height];
}

- (NSRect)rectFromString:(NSString*)string {
    NSRect rect;
    NSArray *array = [string componentsSeparatedByString:@" "];
    rect.origin.x = [[array objectAtIndex:0] floatValue];
    rect.origin.y = [[array objectAtIndex:1] floatValue];
    rect.size.width = [[array objectAtIndex:2] floatValue];
    rect.size.height = [[array objectAtIndex:3] floatValue];
    return rect;
}
person Duncan Groenewald    schedule 21.10.2013