NSUndoManager - 撤消按钮未显示

发布于 2024-12-15 21:44:51 字数 3166 浏览 0 评论 0原文

我有一份包含会议的文档。 当我初始化会议时,我将 undoManager 设置为指向文档的 undoManager。 同样,我的会议有与会者(人员列表)。每个 Person 对象只是指向我的会议的 undoManager,而后者又只是指向 Document 的指针。

在我开始观察人员属性的关键值之前,我对添加和删除会议与会者的撤消一直有效。

关于我做错了什么有什么想法吗?当我添加和删除与会者时,撤消按钮不会激活。同样,当我更改此人的姓名/费率时,撤消按钮不会显示。

文件.m

- (id)init
{
    self = [super init];
    if (self) {
        self.meeting = [[Meeting alloc] init];
        self.meeting.undoManager = self.undoManager;

会议.h ---

@property (nonatomic, retain) NSUndoManager *undoManager;

会议.m

- (void)changeKeyPath:(NSString *)keyPath
         ofObject:(id)obj
          toValue:(id)newValue {
// setValue:forKeyPath: will cause the key-value observing method
// to be called, which takes care of the undo stuff
[obj setValue:newValue forKeyPath:keyPath];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context {
    id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; 
    // NSNull objects are used to represent nil in a dictionary
    if (oldValue == [NSNull null]) {
        oldValue = nil;
}

    [[self.undoManager prepareWithInvocationTarget:self] changeKeyPath:keyPath
                                                          ofObject:object
                                                           toValue:oldValue];
   // Notify the undoManager
   self.undoManager.actionName = @"Edit";

}

- (void)startObservingPerson:(Person *)person {
    // TODO: Understand if I need something for context
    [person addObserver:self
         forKeyPath:@"name"
            options:NSKeyValueObservingOptionOld
            context:nil];

    [person addObserver:self
         forKeyPath:@"rate"
            options:NSKeyValueObservingOptionOld
            context:nil];

}

- (void)stopObservingPerson:(Person *)person    {
    [person removeObserver:self forKeyPath:@"name"];
    [person removeObserver:self forKeyPath:@"rate"];
}

-(void) insertObject:(id *)object inAttendeeListAtIndex:(NSUInteger)index {

    [(Person *)object setMeeting:self];
    // Enable undo capabilities for edits to the name/rate
    [self startObservingPerson:(Person *)object];
    // insert the object / person
    [self.attendeeList insertObject:(Person *)object atIndex:index];

    //
    // configure the undo for the insert
    [[self.undoManager prepareWithInvocationTarget:self] removeObjectFromAttendeeListAtIndex:(NSUInteger) index];

    undoManager.actionName = @"Insert Person";

}

-(void) removeObjectFromAttendeeListAtIndex:(NSUInteger)index {
    Person *deletedPerson = [self.attendeeList objectAtIndex:index];
    // housecleaning before removing the person
    [self stopObservingPerson:(Person *)deletedPerson];

    // remove the object / person
    [self.attendeeList removeObjectAtIndex:index];

    // configure the undo
    [[self.undoManager prepareWithInvocationTarget:self] insertObject:(id *)deletedPerson inAttendeeListAtIndex:index];

    // Notify the undoManager
    undoManager.actionName = @"Remove Person";

}

I have a Document which has a meeting.
When I initialize the meeting, I set the undoManager to point to the Document's undoManager.
Likewise, my meeting has attendees (list of Person). Each Person object simply points back to my meeting's undoManager which in turn is just a pointer to the Document.

My undo for adding and removing attendees to the meeting was working until I started observing the key values for attributes of the person.

Any ideas on what I am doing wrong? When I add and remove an attendee, the undo button does not activate. Likewise, when I make a change to the person's name/rate, the undo button does not show up.

Document.m

- (id)init
{
    self = [super init];
    if (self) {
        self.meeting = [[Meeting alloc] init];
        self.meeting.undoManager = self.undoManager;

meeting.h ---

@property (nonatomic, retain) NSUndoManager *undoManager;

meeting.m

- (void)changeKeyPath:(NSString *)keyPath
         ofObject:(id)obj
          toValue:(id)newValue {
// setValue:forKeyPath: will cause the key-value observing method
// to be called, which takes care of the undo stuff
[obj setValue:newValue forKeyPath:keyPath];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                  ofObject:(id)object
                    change:(NSDictionary *)change
                   context:(void *)context {
    id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; 
    // NSNull objects are used to represent nil in a dictionary
    if (oldValue == [NSNull null]) {
        oldValue = nil;
}

    [[self.undoManager prepareWithInvocationTarget:self] changeKeyPath:keyPath
                                                          ofObject:object
                                                           toValue:oldValue];
   // Notify the undoManager
   self.undoManager.actionName = @"Edit";

}

- (void)startObservingPerson:(Person *)person {
    // TODO: Understand if I need something for context
    [person addObserver:self
         forKeyPath:@"name"
            options:NSKeyValueObservingOptionOld
            context:nil];

    [person addObserver:self
         forKeyPath:@"rate"
            options:NSKeyValueObservingOptionOld
            context:nil];

}

- (void)stopObservingPerson:(Person *)person    {
    [person removeObserver:self forKeyPath:@"name"];
    [person removeObserver:self forKeyPath:@"rate"];
}

-(void) insertObject:(id *)object inAttendeeListAtIndex:(NSUInteger)index {

    [(Person *)object setMeeting:self];
    // Enable undo capabilities for edits to the name/rate
    [self startObservingPerson:(Person *)object];
    // insert the object / person
    [self.attendeeList insertObject:(Person *)object atIndex:index];

    //
    // configure the undo for the insert
    [[self.undoManager prepareWithInvocationTarget:self] removeObjectFromAttendeeListAtIndex:(NSUInteger) index];

    undoManager.actionName = @"Insert Person";

}

-(void) removeObjectFromAttendeeListAtIndex:(NSUInteger)index {
    Person *deletedPerson = [self.attendeeList objectAtIndex:index];
    // housecleaning before removing the person
    [self stopObservingPerson:(Person *)deletedPerson];

    // remove the object / person
    [self.attendeeList removeObjectAtIndex:index];

    // configure the undo
    [[self.undoManager prepareWithInvocationTarget:self] insertObject:(id *)deletedPerson inAttendeeListAtIndex:index];

    // Notify the undoManager
    undoManager.actionName = @"Remove Person";

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

画中仙 2024-12-22 21:44:51

我找到了问题的答案。我通过以下两种方式之一来启动会议。新文档和存档文档。当我从存档加载时,我没有分配 undoManager,因此它为空并且没有发生任何事情

I found the answer to my problem. I initialize meetings one of two ways. New documents and through archived documents. When I was loading from the archive, I wasn't assigning the undoManager so it was null and nothing was happendi

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文