3

我需要知道任何 NSSplitView 子视图的框架何时更改,但只有在它们完成调整大小之后。

目前我在 NSSplitView 子类中使用它:

[[NSNotificationCenter defaultCenter] addObserver: self
                                      selector: @selector(didResize:)
                                      name: NSSplitViewDidResizeSubviewsNotification
                                      object: self];

但我遇到的问题是,当拆分视图正在调整大小或包含窗口更改其帧大小时,这会发送数百个通知。这对性能有很大的不利影响!

一旦拆分视图永久更改了框架,我该如何判断(不增加任何开销或混乱 - 如果调整大小已停止,则每隔一段时间检查一次计时器并不是我真正想要的解决方案)。

4

4 回答 4

1

如果您不想响应每个更改,我认为您需要使用某种计时方法。我认为这样的事情应该工作得很好。只要在 0.1 秒内再次调用该方法,第一行就会取消第二行。

-(void)splitViewDidResizeSubviews:(NSNotification *)notification {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(respondToSubviewChange) object:nil];
    [self performSelector:@selector(respondToSubviewChange) withObject:nil afterDelay:.1];
}

-(void)respondToSubviewChange {
    NSLog(@"here");
   // Do your work here.
}

顺便说一句,如果此代码所在的类是拆分视图的委托,那么您无需注册此通知,它会自动注册。

编辑后:

我确实找到了另一种不使用任何计时机制的方法,但我不知道它有多强大。它依赖于 splitView:constrainMinCoordinate:ofSubviewAt: 当你在分隔器中使用 mouseDown 时调用的事实,然后再次使用 mouseUp。它在应用程序第一次启动时也被调用一次(或者可能在拆分视图所在的窗口、加载或其他什么时候——我没有用多个窗口测试它)。因此,将“timesCalled”设置为 -1(而不是 0)是为了让逻辑在应用程序启动时忽略第一次调用。此后,if 子句在对委托方法的所有其他调用(将在 mouseUp 上)评估为 true。

- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex {
    static int timesCalled = -1;
    if (timesCalled % 2 == 1) {
        NSLog(@"Do stuff");
        // Do your work here.
    }
    timesCalled ++;
    return 0 // 0 allows you to minimize the subview all the way to 0;
}
于 2013-05-18T01:26:31.907 回答
0

您可以从子类的窗格拆分器中查找 mouseDown mouseDragged 和 mouseUp 事件。那时您可以使用它来发布来自子类的通知。您可以检查现有的 NSSplitView 子类,例如古老的 RBSplitView,看看它们是否已经完成了您想要的操作。

于 2013-05-18T08:06:31.113 回答
0

仅实现此委托方法。当我实现其他调整大小的委托方法时,结果一团糟。

每次鼠标移动时都会调用此方法,释放鼠标时会再次调用此方法。

-(void)splitViewDidResizeSubviews:(NSNotification *)notification{

if (notification.object == self.contentSplitView){ //get the right splitview

    static CGFloat last = 0; //keep tracks with widths
    static BOOL didChangeWidth = NO; //used to ignore height changes

    CGFloat width_new = self.tableview_images.frame.size.width; //get the new width
    if (last == width_new && didChangeWidth){ //
        [self.tableview_images reloadData];

        NSLog(@"finish!");
        didChangeWidth = NO;

    } else {


        if (last != width_new){
            if (last != 0){
                didChangeWidth = YES;
            }
        }
    }
    last = width_new;

}

}

于 2015-03-11T16:10:04.397 回答
0

viewDidEndLiveResizeNSSplitView在调整窗口大小和拖动分隔线后调用。您可以使用它发送自定义通知。

extension Notification.Name {
    static public let didEndLiveResize = Notification.Name("didEndLiveReze")
}

class SplitView: NSSplitView
{
    override func viewDidEndLiveResize() {
        super.viewDidEndLiveResize()
        NotificationCenter.default.post(name: .didEndLiveResize, object: self)
    }
}
于 2021-06-30T12:18:50.727 回答