2

我有一个 UI,其中NSCollectionViewItemView 的内容是通过 CALayers 以编程方式绘制的。我CAConstraintLayoutManager在调整大小时使用 a 来保持子图层的布局一致,但是这样做时我的性能非常差。似乎调整窗口大小会导致调整两个CATextLayers 的大小以使其适合根层的宽度,并重新定位一个CATextLayer以使其保持右对齐,这会导致应用程序花费大部分时间来执行该CGSScanConvolveAndIntegrateRGB功能(我使用了 Time Profiler 仪器)。

最“昂贵”的层(即使是唯一显示的也会导致最卡顿的层)是一个包裹的 multiline CATextLayer。我完全不知道如何获得更好的性能(我试过不使用 aCAConstraintLayoutManager和层对齐,但我得到了同样的东西)。有人遇到过这个问题吗?有办法解决吗?

PS:我已经对布局管理器进行了子类化,并在执行期间- (void)layoutSublayersOfLayer:(CALayer *)layer通过将 YES 设置为禁用了所有动画kCATransactionDisableActionsCATransaction但这似乎没有帮助。

编辑:我禁用了文本图层的字体平滑,性能提高了一点(很少),但它在 _ZL9view_drawP7_CAViewdPK11CVTimeStampb 中花费了大量的时间(这是由 ATI Radeon 驱动程序的线程调用的东西,我认为)。

4

1 回答 1

1

我解决了。有点儿。对我来说,这似乎仍然是一个肮脏的黑客,但我不知道如何setNeedsDisplayInRect工作,所以我最终这样做了:

  1. 在 NSWindow 委托中:

    -(void)windowWillStartLiveResize:(NSNotification *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:@"beginResize" object:nil]; }

    -(void)windowDidEndLiveResize:(NSNotification *)notification { [[NSNotificationCenter defaultCenter] postNotificationName:@"endResize" object:nil];
    }

  2. 在我的自定义视图中,这两个通知分别调用了-(void)beginResize-(void)endResize选择器。第一个将 BOOL inLiveResize 变量设置为 YES,而第二个将其设置为 NO 并使用新的帧大小再次调用 setFrameSize。

  3. 我覆盖(覆盖?不是以英语为母语的人,抱歉)这样的-(void)setFrameSize:(NSSize)newSize方法:

    -(void)setFrameSize:(NSSize)newSize 
    {        
        if (inLiveResize) {
            NSRect scrollFrame = [[[self superview] enclosingScrollView] documentVisibleRect];
    
            BOOL condition1 = (self.frame.origin.y > (scrollFrame.origin.y - self.frame.size.height));
            BOOL condition2 = (self.frame.origin.y < (scrollFrame.origin.y + scrollFrame.size.height + self.frame.size.height));
    
            if (condition1 && condition2)
                [super setFrameSize:newSize];
        }
        else {
            [super setFrameSize:newSize]; }}
    

就是这样。这样,只有可见视图随窗口一起调整大小,而其他视图在操作结束时重新绘制。它可以工作,但我不喜欢它有多“脏”,我确信有一种更优雅的内置(ish)方法可以通过使用该setNeedsDisplayInRect方法来做到这一点。我会研究更多。

于 2011-11-29T16:49:05.137 回答