我有一个UI,其中NSCollectionViewItem
的视图的内容是通过calayer编程绘制的。在调整大小时,我使用CAConstraintLayoutManager
来保持子层的布局一致,但是这样做时我的性能非常差。似乎调整窗口的大小,这会导致两个CATextLayer
s的大小调整,使它们适合根层的宽度,以及一个CATextLayer
的重新定位,使其保持右对齐,导致应用程序花费大部分时间执行CGSScanConvolveAndIntegrateRGB
函数(我使用了时间分析器工具)。
最"昂贵"的一层(即使它是唯一显示的一层,也会导致最口吃的一层)是一个包装的多行CATextLayer
。我完全不知道如何获得更好的性能(我试过不使用CAConstraintLayoutManager
和图层对齐,但我得到了同样的东西)。有人遇到过这个问题吗?有别的办法吗?
PS:我已经子类化了布局管理器,并通过在CATransaction
中将YES设置为kCATransactionDisableActions
,在- (void)layoutSublayersOfLayer:(CALayer *)layer
执行期间禁用了所有动画,但它似乎没有帮助。
编辑:我已经禁用了字体平滑的文本层和性能增加了一点点(非常少),但它花费了一个可怕的时间在_ZL9view_drawP7_CAViewdPK11CVTimeStampb(这是由ATI Radeon驱动程序的线程调用的东西,我想)。
我解决了。种。这对我来说似乎仍然是一个肮脏的hack,但我无法找到如何使setNeedsDisplayInRect
工作,所以我最终这样做:
-
NSWindow委托中:
- (void) windowWillStartLiveResize: (NSNotification *)通知{[[NSNotificationCenter defaultCenter] postNotificationName:@"beginResize"对象:nil];}
- (void) windowDidEndLiveResize: (NSNotification *)通知{[[NSNotificationCenter defaultCenter] postNotificationName:@"endResize" object:nil];
} -
在自定义视图中,这两个通知分别调用
-(void)beginResize
和-(void)endResize
选择器。第一个将BOOL变量inLiveResize设置为YES,而第二个将其设置为NO,并使用新的帧大小再次调用setFrameSize。 -
I overrode (overridden?不是英语为母语的人,抱歉)
-(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]; }}
就是这样。这样,只有可视视图与窗口一起调整大小,而其他视图在操作结束时重新绘制。它可以工作,但我不喜欢它有多"脏",我确信有一个更优雅的,内置的(类似的)方法,通过使用setNeedsDisplayInRect
方法来做到这一点。我会做更多的研究。