我在我的应用程序中的纹理 NSWindows 上也遇到了上面提到的渐变问题,但我花了很长时间才找到这篇有助于解决问题的帖子。
我希望在此帖子中添加更多内容,以便如果其他开发人员发现他们遇到相同的问题,那么将来可能会更容易地找到解决方案。
就我而言,我构建了一个带有一组纹理窗口的应用程序。与 Dimillian77 的问题类似,我的应用程序的主窗口背景纹理受到子视图的大小和位置的影响,在我的情况下,这些是主窗口的 NSWindowController 根据哪个区域切换进/出的各种 NSView 子视图用户正在访问的应用程序。由于每个子视图的 NSView 子视图的大小和位置略有不同,因此当用户在每个视图之间切换时,渐变错误更加明显,因为主窗口的背景渐变会在子视图后面跳跃。
有趣的是,渐变问题仅在过渡到 OS X 10.7 Snow Leopard 后出现——相同的、未修改的源代码和 .xib/.nib 文件在任何早期版本的 OS X 上都不会导致此问题。这似乎同意 cocoahero 的建议,即这个问题可能是一个值得 Radar 报告的新错误——也许我们会发现它已在 Mountain Lion 中得到修复?
事实上,我的应用程序的主 NSWindow 和几个支持窗口都设置为使用“纹理”(金属)背景选项,但只有在迁移到 Snow Leopard 之后,渐变“错误”才出现。
在找到这篇文章之前,我偶然发现“解决”问题的唯一方法是注意到如果窗口启用了“调整大小”控件,渐变错误就会消失!
但是,我不希望我的特定应用程序窗口可以调整大小,并且我可以使用-(void)setShowsResizeIndicator:(BOOL)showResizeIndicator 禁用标题栏“调整大小”控件,并通过拦截调用来覆盖用户调整窗口大小的尝试-(NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize,这显然不是一个优雅的解决方案或要走的路。这个解决方案特别失败,因为窗口仍然显示其调整大小的鼠标光标(我无法隐藏),因为这些让用户感到困惑,因为我在代码中覆盖了任何调整窗口大小的尝试。
值得庆幸的是,cocoahero 将“内容边框”设置更改为“无”的解决方案立即使渐变问题在 Interface Builder(与 Xcode 4.3.3 集成的版本)中消失了,但至少在我的情况下,在最初编译时并在进行此更改后运行应用程序,一旦加载 .xib 文件,应用程序就会崩溃。跟踪中出现以下错误消息:“setAutorecalculatesContentBorderThickness:forEdge: may not be called with NSMaxYEdge in a non-textured window”。
我发现将“内容边框”设置为“自定义”并将“顶部”和“底部”内容边框设置为“1”解决了崩溃问题,尽管奇怪的是在使用“自定义”保存和编译应用程序之后设置到位后,我通过实验发现我可以将“自定义边框”设置更改为“无”并编译应用程序并使其在第二次编译时正常运行。
但是,将“内容边框”更改为“自动调整大小”以外的任何内容会导致 XCode 中出现数十个“非法配置:Mac OS X 10.7 之前的自动布局”错误,以及一些“属性不可用: 10.6 之前的 Mac OS X 版本上的顶部/底部内容边框属性的 Autosize 以外的值“错误 - 都与“内容边框”属性有关(我的部署目标设置为 OS X 10.6 而不是 10.7)。因此,继续寻找错误的另一种解决方案,这使我找到了下面详述的解决方案。我发现的解决方案,至少在 OS X 10.7 上,是在 Interface Builder 中将每个纹理窗口的“内容边框”设置回“自动调整大小”,而是覆盖代码中的内容边框设置(在我的情况下,通过放置此代码进入我的每个纹理窗口的 NSWindowController 类):
// windowDidLoad is called when the window has loaded but before it's displayed...
-(void)windowDidLoad
{
// set the content border thickness to 0 for both the top and bottom window edges
[[super window] setContentBorderThickness:0 forEdge:NSMaxYEdge]; // top border
[[super window] setContentBorderThickness:0 forEdge:NSMinYEdge]; // bottom border
// disable the auto-recalculation of the window's content border
[[super window] setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
[[super window] setAutorecalculatesContentBorderThickness:NO forEdge:NSMinYEdge];
}
请注意,您只能在纹理窗口上设置顶部内容边框粗细,如果您尝试在其他 NSWindow 类型上通过代码或通过界面生成器进行设置,系统将引发异常,可能导致应用程序崩溃。
根据 NSWindow 文档:“在调用 setContentBorderThickness:forEdge 的非纹理窗口中:传递 NSMaxYEdge 将引发异常。仅在纹理窗口中设置顶部边缘的内容边框厚度才有效。”
由于渐变问题确实似乎是 OS X 10.7 渲染“纹理”窗口中的一个新错误,因此修改任何覆盖内容边界的代码以使此类代码仅在运行的系统上执行可能是明智之举OS X 10.7(如果 Mountain Lion 中的问题仍未解决,可能还有未来的 OS X 版本)。
我希望这篇文章有用,这个错误确实令人困惑,并且比我希望解决的时间要长得多。由于这个问题的文档似乎很少,我觉得值得花时间发布我的发现,希望它可以节省其他人的时间,并希望通过在线搜索让这个问题有更多的曝光度和关键字。
感谢 cocoahero,如果没有他们的回答,我和其他许多人仍然会努力解决这个问题。