2

我有一个应用程序可以记录音频并在屏幕上绘制波形(以及其他一些元素)。录制时,我想在 .containerView 中绘制波形NSScrollView。containerView 不断扩展以容纳新的音频信息并不断滚动到最后。这种行为与 GarageBand 中的滚动视图在记录新信息时的行为完全相同。

drawRect:虽然我已经知道如何做到这一点,但我的系统在滚动时似乎使用了不必要的调用次数。执行此操作的最有效方法是什么(更新 contentView 大小,在扩展区域上绘制新内容,然后滚动以使结尾可见?不知何故,一旦 containerView 宽度较大,我的每次滚动都会调用 drawRect 5次-比滚动视图聪明

设置滚动条的文档视图:

[self.scrollView setDocumentView:self.containerView];

进一步滚动的方法(从 调用NSTimer):

- (void)scrollFurther {   
    scrollPoint = ([SSSubdivisionManager manager].lastStartSample + [RemoteIOPlayer remote].diffInFrames) / (zoomLevel * baseZoomLevel);
    int scrollWidth = self.scrollView.frame.size.width;
    CGRect frame = self.containerView.frame;

    if (scrollPoint >= ((scrollPoint + (scrollWidth * 0.5f) ) / 2)) {
        if (![SSAudioManager manager].isDoingInputPlayback) {
            frame.size.width = scrollPoint + (scrollWidth * 0.5f);

            NSLog(@"Setting scroller frame to: %@", NSStringFromRect(frame));

            [self.containerView setFrame:frame];
        }

        NSPoint p = NSMakePoint(scrollPoint - (scrollWidth * 0.5), 0);
        NSLog(@"Scrolling to point %@", NSStringFromPoint(p));
        [self.containerView scrollPoint:p];
    } else {
        NSLog(@"Not exapanding frame or scrolling to a point");
        [self.containerView setNeedsDisplayInRect:frame];
    }
}

结果日志调用:

一开始,当containerView小于scrollView时:

2012-07-29 17:42:43.607 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{0, 0}, {1924, 700}}
2012-07-29 17:42:43.683 MET[4679:503] Setting scroller frame to: {{0, 0}, {1942.3199462890625, 700}}
2012-07-29 17:42:43.684 MET[4679:503] Scrolling to point {580.3199462890625, 0}
2012-07-29 17:42:43.687 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{0, 0}, {1942, 700}}
2012-07-29 17:42:43.757 MET[4679:503] Setting scroller frame to: {{0, 0}, {1957.6800537109375, 700}}
2012-07-29 17:42:43.758 MET[4679:503] Scrolling to point {595.6800537109375, 0}
2012-07-29 17:42:43.760 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{0, 0}, {1957, 700}}
2012-07-29 17:42:43.835 MET[4679:503] Setting scroller frame to: {{0, 0}, {1975.5999755859375, 700}}
2012-07-29 17:42:43.836 MET[4679:503] Scrolling to point {613.5999755859375, 0}
2012-07-29 17:42:43.839 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{0, 0}, {1975, 700}}
2012-07-29 17:42:43.889 MET[4679:503] Setting scroller frame to: {{0, 0}, {1988.4000244140625, 700}}
2012-07-29 17:42:43.890 MET[4679:503] Scrolling to point {626.4000244140625, 0}
2012-07-29 17:42:43.892 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{0, 0}, {1988, 700}}

然后,它失控了:

2012-07-29 17:42:43.954 MET[4679:503] Setting scroller frame to: {{0, 0}, {2001.199951171875, 700}}
2012-07-29 17:42:43.956 MET[4679:503] Scrolling to point {639.199951171875, 0}
2012-07-29 17:42:43.960 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 512}, {465.199951171875, 188}}
2012-07-29 17:42:43.961 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 512}, {512, 188}}
2012-07-29 17:42:43.964 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 512}, {512, 188}}
2012-07-29 17:42:43.971 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 0}, {465.199951171875, 512}}
2012-07-29 17:42:43.972 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 0}, {512, 512}}
2012-07-29 17:42:43.977 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 0}, {512, 512}}
2012-07-29 17:42:44.098 MET[4679:503] Setting scroller frame to: {{0, 0}, {2034.47998046875, 700}}
2012-07-29 17:42:44.099 MET[4679:503] Scrolling to point {672.47998046875, 0}
2012-07-29 17:42:44.104 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 512}, {498.47998046875, 188}}
2012-07-29 17:42:44.107 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 512}, {512, 188}}
2012-07-29 17:42:44.112 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 512}, {512, 188}}
2012-07-29 17:42:44.118 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 0}, {498.47998046875, 512}}
2012-07-29 17:42:44.120 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 0}, {512, 512}}
2012-07-29 17:42:44.125 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 0}, {512, 512}}
2012-07-29 17:42:44.154 MET[4679:503] Setting scroller frame to: {{0, 0}, {2047.280029296875, 700}}
2012-07-29 17:42:44.155 MET[4679:503] Scrolling to point {685.280029296875, 0}
2012-07-29 17:42:44.157 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 512}, {511.280029296875, 188}}
2012-07-29 17:42:44.159 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 512}, {512, 188}}
2012-07-29 17:42:44.162 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 512}, {512, 188}}
2012-07-29 17:42:44.168 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1536, 0}, {511.280029296875, 512}}
2012-07-29 17:42:44.172 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{1024, 0}, {512, 512}}
2012-07-29 17:42:44.178 MET[4679:503] -[SSVisualContainer drawRect:] [Line 70] Drawrect: {{512, 0}, {512, 512}}
4

2 回答 2

1

在这种实时应用程序中,您应该考虑使用图层而不是绘制到重载drawRect:方法的 UIView。

也许您可以使用 CoreGraphics 函数将每条新波形绘制成位图(非常快,因为它们不会写入显示器),然后创建一个新的 CALayer,将图像放入其中并将其定位在你的容器视图。

context = CGBitmapContextCreate(etc...);
// draw your graphic (waveform) into the context
CALayer *newlayer = [CALayer layer];
newlayer.contents = CGBitmapContextCreateImage (context);
newlayer.position = CGPointMake(...at the end of container...);
[container.layer addSublayer: newlayer];

您的容器视图的图层将具有与您绘制的波形块一样多的子图层,一个在另一个旁边。

图层非常快,并且由于您已经绘制的波浪不会改变,它们将快速渲染为位图并很好地滚动。

于 2012-08-07T22:47:46.367 回答
0

在初始化中你可以调用 [self setwantslayer:YES]; 这样,ns 控件会自动添加一个 CALayer 并使用 chache 处理绘图调用。

于 2013-11-23T23:57:55.443 回答