删除索引 0 处的 CALayer

问题描述 投票:0回答:7

我添加了渐变层:

[theView.layer insertSublayer:gradient atIndex:0];

后来在另一种方法中我想删除这一层。我想我应该获取子层数组,然后获取索引 0 处的子层并对其调用removeFromSuperlayer。这是正确的方法吗?如果不正确,你可以这样做吗?

干杯。

iphone uiview calayer
7个回答
20
投票

您可以按照您描述的方式进行操作,但不太可靠。问题是,如果您在添加和删除之间对子图层执行任何操作,子图层的索引可能会发生变化,最终会删除您不想删除的内容。

最好的办法是保留对该层的引用,稍后当您想删除它时只需调用

[theLayer removeFromSuperlayer]

希望有帮助


11
投票

有趣有趣...

您可以使用两个图层属性(在任何一种情况下,您都必须迭代图层):

  • CALayer.name
    “被一些布局管理器用来识别图层”。将其设置为合理保证唯一的值(例如“MyClassName.gradient”)。
  • CALayer.style
    是一本字典。您可以使用 CoreAnimation 未使用的键(例如
    NSMutableDictionary * d = [NSMutableDictionary dictionaryWithDictionary:layer.style]; [d setValue:[NSNumber numberWithBool:YES] forKey:@"MyClassName.gradient"]; layer.style = d;
    )。这对于将任意数据与视图关联可能很有用(例如包含文本字段的单元格的索引路径......)。

(我假设

[NSDictionary dictionaryWithDictionary:nil]
返回空字典,而不是返回 nil 或抛出异常。
[NSArray arrayWithArray:nil]
对应的情况也是如此。)

但是,额外的代码复杂性、性能损失和出错的可能性可能超过内存使用量的小幅下降。如果您有少量视图,每个视图 4 字节并不算多(即使您有负载,4 字节也是单个像素使用的内存!)。


6
投票

Swift 有一些非常简单的解决方案:

// SWIFT 4 update
func removeSublayer(_ view: UIView, layerIndex index: Int) {
    guard let sublayers = view.layer.sublayers else {
        print("The view does not have any sublayers.")
        return
    }
    if sublayers.count > index {
        view.layer.sublayers!.remove(at: index)
    } else {
        print("There are not enough sublayers to remove that index.")
    }
}
// Call like so
removeSublayer(view, layerIndex: 0)

请记住,子层被视为数组,因此如果计数为 2,则索引中的 2 == 1,因此

removeAtIndex(1)

有一大堆选项可用于编辑子图层。只需在

sublayers!.
之后停止输入并检查它们即可。


5
投票

旧帖子..但这可能对某人有帮助...

我删除/替换 CALayer 的实现。 使用 Calayer.name 作为 tc。如上所述。

CAGradientLayer *btnGradient = [CAGradientLayer layer];
btnGradient.frame = button.bounds;
btnGradient.name = @"gradient";
btnGradient.colors = nil;
btnGradient.colors = [NSArray arrayWithObjects:
                      (id)[[VOHelper getButtonColor:kSchemeBorder] CGColor],
                      (id)[[VOHelper getButtonColor:kSchemeButton] CGColor],
                      nil];

if ([[[[button.layer sublayers] objectAtIndex:0] name] isEqualToString:btnGradient.name])
{
       [button.layer replaceSublayer:[[button.layer sublayers] objectAtIndex:0] with:btnGradient];
}
else
{
    [button.layer insertSublayer:btnGradient atIndex:0];
}

4
投票

斯威夫特4

  self.view.layer.sublayers = self.view.layer.sublayers?.filter { theLayer in
        !theLayer.isKind(of: CAGradientLayer.classForCoder())
  }

1
投票

这对我 Swift 5 有用

    if let _ = self.layer.sublayers?.first as? CAGradientLayer {
        print("Debug: Gradient sublayer Found.")
        self.layer.sublayers?[0] = gradient
    }
    else {
        print("Debug: Non Gradient Layer Found in Sublayer 0.")
        self.layer.insertSublayer(gradient, at: 0)
    }

0
投票

这对我来说适用于任何 UIView

func removeGradient() {
    if let gradientLayer = self.layer.sublayers?.first as? CAGradientLayer {
        gradientLayer.removeFromSuperlayer()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.