核心动画 - 使用 `makeBackingLayer` 不适用于核心图像过滤器。

3
我正在构建一个使用 CALayer 的 NSView,该视图应用遮罩过滤器到层上,然后绘制这个层。当我手动在 -(void)viewDidMoveToSuperview) 中构建一个新的层并将其设置在视图上时,视图正确地呈现,但是当我覆盖 -(CALayer *)makeBackingLayer 时,过滤器不会被应用到层上。
下面是能正常工作的代码(使用层主机视图样式):
-(void)viewDidMoveToSuperview{
  [super viewDidMoveToSuperview];
  CIFilter *filter = [CIFilter filterWithName:@"CIBlendWithMask"];
  [filter setValue:[self transparentImage] forKey:@"inputBackgroundImage"];
  [filter setValue:[self maskImage] forKey:@"inputMaskImage"];

  self.layer = [TransparentLayer layer];
  self.layer.backgroundColor = CGColorCreateGenericRGB(0, 1, 1, 1);

  [self.layer setPosition:CGPointMake(0 ,0)];
  [self.layer setAnchorPoint:CGPointMake(0 ,0)];
  [self.layer setBounds:CGRectMake(0 ,0 ,200, 200)];
  self.layer.filters = [NSArray arrayWithObject:filter];
  [self setWantsLayer:YES];
  [self.layer setNeedsDisplay];
  [self setNeedsDisplay:YES];
}

这将呈现CALayer并输出结果如下所示: Layer Host 但是当我使用此方法(支持图层的视图样式)时:
-(CALayer *)makeBackingLayer{

  CIFilter *filter = [CIFilter filterWithName:@"CIBlendWithMask"];
  [filter setValue:[self transparentImage] forKey:@"inputBackgroundImage"];
  [filter setValue:[self maskImage] forKey:@"inputMaskImage"];

  TransparentLayer *backingLayer = [TransparentLayer layer];
  backingLayer.backgroundColor = CGColorCreateGenericRGB(0, 1, 1, 1);

  [backingLayer setPosition:CGPointMake(0 ,0)];
  [backingLayer setAnchorPoint:CGPointMake(0 ,0)];
  [backingLayer setBounds:CGRectMake(0 ,0 ,200, 200)];
  backingLayer.filters = [NSArray arrayWithObject:filter];
  return backingLayer;

}

-(void)viewDidMoveToSuperview{
  [super viewDidMoveToSuperview];
  [self setWantsLayer:YES];
}

视图最终看起来是这样的: Layer Backed View (Broken) 两个问题:
1 - 使用makeBackingLayer时为什么不对层应用过滤器?
2 - 我如何使用makeBackingLayer生成层,而不是调用setLayer
编辑:将-(void)viewDidMoveToSuperView更改为以下内容可以呈现我想要的图层,但这仍然没有回答我的问题:
-(void)viewDidMoveToSuperview{
  [super viewDidMoveToSuperview];
  //manually set the layer
  [self setLayer:[self makeBackingLayer]];
  [self setWantsLayer:YES];
}
1个回答

3

由于您正在访问视图层的属性,因此您必须使视图成为主机层而不是支持层。

您不能使用-makeBackingLayer来自定义视图的层。文档仅提到了此方法的一个应用:

在您的视图类中,重写-makeBackingLayer以返回您的NSOpenGLLayer子类的自动释放实例。

  1. 因为您应该使用-setContentFilters:
  2. 您不能。您必须调用setLayer:

-makeBackingLayer不是创建自定义层的正确位置。您应该添加新的方法(例如-makeHostLayer)。


答案 #1(使用“-setContentFilters:”)对我无效。(那是一个旧的API还是iOS特定的?)但是,总体答案(使用层托管视图而不是层支持视图)是正确的。谢谢Kentzo。 - jacobsimeon
如果您的视图仅为层支持,则“-setContentFilters:”才有效。 - Kentzo
1
我认为这不是100%正确的,一般来说你可以使用makeBackingLayer来创建自己的后备层,并且在核心动画编程指南的“设置图层对象”一节中有记录。你必须调用setWantsLayer:来实现这个功能。其余部分是正确的,后备层并不是托管层。 - Stephan
在重新访问我写的一些非常古老的代码时,我偶然发现了自己的答案。截至10.15版本,覆盖-makeBackingLayer:以返回_custom_图层仍会对视图产生影响,而AppKit则不会干涉它。 - Kentzo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接