Менеджер отмены с несколькими полями

Здравствуйте, у меня есть приложение, оно очень простое, но в нем есть несколько полей для адреса, например города, почтового индекса, штата и т. д.

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

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

Я не знаю, как быстро, поэтому, пожалуйста, ответьте в Obj-c, чтобы я мог понять, что нужно сделать.

Документация: NSUndoManager и Архитектура отмены.

Willeke 20.07.2024 07:09
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот небольшой пример для начала.

  1. Начните с шаблона приложения Xcode macOS.
  2. Добавьте приведенный ниже код в AppDelegate.m.
  3. Добавьте в окно несколько элементов управления (NSTextField или другой подкласс NSControl).
  4. Подключите действие элементов управления к controlAction:.
@interface AppDelegate ()

@property (strong) IBOutlet NSWindow *window;

// values before editing, the key is the identifier of the control
@property (strong) NSMutableDictionary *data;

@end


@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.data = [[NSMutableDictionary alloc] init];
}

- (void)undoControl:(NSControl *)control oldValue:(id)oldValue newValue:(id)newValue {
    // undo
    NSString *controlID = control.identifier;
    [control setObjectValue:oldValue];
    self.data[controlID] = oldValue;
    if (control.acceptsFirstResponder)
        [self.window makeFirstResponder: control];
    // register redo
    NSLog(@"register redo %@ old:'%@' new:'%@'", controlID, oldValue, newValue);
    [[self.window.undoManager prepareWithInvocationTarget:self] undoControl:control
        oldValue:newValue newValue:oldValue];
}

- (IBAction)controlAction:(NSControl *)control {
    NSString *controlID = control.identifier;
    id oldValue = self.data[controlID];
    id newValue = control.objectValue;
    if (oldValue != newValue && ![oldValue isEqual:newValue]) {
        // register undo
        NSLog(@"register undo %@ old:'%@' new:'%@'", controlID, oldValue, newValue);
        [[self.window.undoManager prepareWithInvocationTarget:self] undoControl:control
            oldValue:oldValue newValue:newValue];
        self.data[controlID] = newValue;
    }
}

@end

Спасибо, Виллеке, я посмотрю код и пойму, как все это работает, я ценю ваше время.

GeraldTheGerm 23.07.2024 15:08

Я отметил ваш ответ как лучший и получил одобрение — он был невероятно полезен, все, что я искал в Интернете, казалось очень сложным и утомительным, но ваш фрагмент кода помог мне увидеть все необходимое, и его очень легко понять. Я заметил одну вещь: когда я впервые изменяю поле, старое значение становится NULL - поэтому для таких вещей, как раскрывающиеся меню, когда вы выполняете окончательную отмену, вы переходите к несуществующей пустой опции в раскрывающемся списке. регистрация отмены _NS:454 старый:'(null)' новый:'4' Есть идеи, почему он отображается как нулевой?

GeraldTheGerm 23.07.2024 16:47

Доступно ли какое-либо уведомление, которое может получить значение поля или другого элемента управления при его выборе? Я изо всех сил пытаюсь найти что-нибудь в Интернете.

GeraldTheGerm 24.07.2024 09:50

Свойство data инициализируется неправильно и все старые значения равны нулю. Он должен быть заполнен начальными значениями элементов управления. Большинство элементов управления могут иметь делегата и/или отправлять уведомления, например NSControlTextDidBeginEditingNotification и NSPopUpButtonWillPopUpNotification. Ознакомьтесь с документацией по методам класса и делегата с аргументом уведомления. Также проверьте суперкласс.

Willeke 24.07.2024 19:58

Привет, Виллеке, ранее я просматривал NSControlTextDidBeginEditingNotification для текстовых полей, но я смог запустить его только после того, как внес изменение, поэтому я не мог заставить его получить начальное значение, а только первое измененное значение. Как инициализировать данные правильно получить начальные значения

GeraldTheGerm 24.07.2024 22:44

Другое решение — получить начальные значения в viewDidLoad или awakeFromNib.

Willeke 25.07.2024 13:39

Я так и думал, но есть 30-40 хороших полей, я имею в виду, что я мог бы сохранить их в plist или что-то в этом роде, однако в функции controlAction, как мне сослаться на правильное начальное значение элемента управления? Я благодарен за вашу помощь :) Я удивлен, что нет уведомления о подобном фокусе поля - это было бы проще, поскольку я мог бы просто захватить значение фокуса поля - а затем сохранить его как oldValue.

GeraldTheGerm 25.07.2024 16:37

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

GeraldTheGerm 25.07.2024 17:00

Другие вопросы по теме