Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone iOS核心动画:CALayer bringSublayerToFront?_Iphone_Objective C_Ios_Core Animation_Calayer - Fatal编程技术网

Iphone iOS核心动画:CALayer bringSublayerToFront?

Iphone iOS核心动画:CALayer bringSublayerToFront?,iphone,objective-c,ios,core-animation,calayer,Iphone,Objective C,Ios,Core Animation,Calayer,如何将CALayer子层带到所有子层的前面,类似于-[UIView bringSubviewToFront]?我认为不存在这样的方法,但很容易自己滚动 // CALayer+Additions.h @interface CALayer (Additions) - (void)bringSublayerToFront:(CALayer *)layer; - (void)sendSublayerToBack:(CALayer *)layer; @end // CALayer+Additions.

如何将
CALayer子层
带到所有子层的前面,类似于
-[UIView bringSubviewToFront]

我认为不存在这样的方法,但很容易自己滚动

// CALayer+Additions.h

@interface CALayer (Additions)
- (void)bringSublayerToFront:(CALayer *)layer;
- (void)sendSublayerToBack:(CALayer *)layer;
@end

// CALayer+Additions.m

@implementation CALayer (Additions)

- (void)bringSublayerToFront:(CALayer *)layer {
    CALayer *superlayer = self.superlayer;
    [self removeFromSuperlayer];
    [superlayer insertSublayer:gradientLayer atIndex:[self.sublayers count]-1];
}

- (void)sendSublayerToBack:(CALayer *)layer {
    CALayer *superlayer = self.superlayer;
    [self removeFromSuperlayer];
    [superlayer insertSublayer:gradientLayer atIndex:0];
}

这是@MattDiPasquale实现的变体,更准确地反映了UIView的逻辑:

- (void) bringSublayerToFront:(CALayer *)layer
{
    [layer removeFromSuperlayer];
    [self insertSublayer:layer atIndex:[self.sublayers count]];
}

- (void) sendSublayerToBack:(CALayer *)layer
{
    [layer removeFromSuperlayer];
    [self insertSublayer:layer atIndex:0];
}
注意:如果您不使用ARC,您可能希望在两个函数的顶部添加
[层保留]
,在底部添加
[层释放]
,以确保
在保留计数=1的情况下不会意外破坏。

此处是正确的代码

- (void)bringSublayerToFront:(CALayer *)layer {
    CALayer *superlayer = layer.superlayer;
    [layer removeFromSuperlayer];
    [superlayer insertSublayer:layer atIndex:[superlayer.sublayers count]];
}

- (void)sendSublayerToBack:(CALayer *)layer {
    CALayer *superlayer = layer.superlayer;
    [layer removeFromSuperlayer];
    [superlayer insertSublayer:layer atIndex:0];
}

这是正确的代码:

-(void)bringSubLayerToFront:(CALayer*)layer
{
  [layer.superLayer addSubLayer:layer];
}

-(void)sendSubLayerToBack:(CALayer*)layer
{
  [layer.superlayer insertSublayer:layer atIndex:0];
}

我很好奇为什么这些答案都没有提到CALayer上的zPosition属性。核心动画查看此属性以确定层渲染顺序。值越高,它越靠近前面。只要zPosition为0,这些答案都有效,但要轻松地将层置于最前面,请将其zPosition值设置为高于所有其他子层。

您可以在CALayer上的类别中实现此功能,如下所示:

CALayer+Extension.h

#import <QuartzCore/QuartzCore.h>

typedef void (^ActionsBlock)(void);

@interface CALayer (Extension)

+ (void)performWithoutAnimation:(ActionsBlock)actionsWithoutAnimation;
- (void)bringSublayerToFront:(CALayer *)layer;

@end

为了便于访问,您可以在项目的Prefix.pch(预编译头)文件中导入“CALayer+Extension.h”。

创建一个CALayer类别,如下所示:

@interface CALayer (Utils)

- (void)bringSublayerToFront;

@end

@implementation CALayer (Utils)

- (void)bringSublayerToFront {
    CGFloat maxZPosition = 0;  // The higher the value, the closer it is to the front. By default is 0.
    for (CALayer *layer in self.superlayer.sublayers) {
        maxZPosition = (layer.zPosition > maxZPosition) ? layer.zPosition : maxZPosition;
    }
    self.zPosition = maxZPosition + 1;
}

@end
Swift 4版本。
层本身具有
bringToFront
sendToBack
方法的想法

#if os(iOS)
   import UIKit
#elseif os(OSX)
   import AppKit
#endif

extension CALayer {

   func bringToFront() {
      guard let sLayer = superlayer else {
         return
      }
      removeFromSuperlayer()
      sLayer.insertSublayer(self, at: UInt32(sLayer.sublayers?.count ?? 0))
   }

   func sendToBack() {
      guard let sLayer = superlayer else {
         return
      }
      removeFromSuperlayer()
      sLayer.insertSublayer(self, at: 0)
   }
}

用法:

let view = NSView(frame: ...)
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.gray.cgColor

let l1 = CALayer(...)
let l2 = CALayer(...)

view.layer?.addSublayer(l1)
view.layer?.addSublayer(l2)

l1.bringToFront()

有没有机会解释一下为什么有人否决了这一点?可能是因为代码错了。未使用参数层。未定义gradientLayer。不需要superlayer调用,因为layer参数的superlayer是self。ivanzoid已发布更正的代码。
removeFromSuperlayer
方法是不必要的,因为调用
insertSublayer
时会自动删除它。removeFromSuperlayer的另一个问题是:如果层是唯一的子层,删除它显然会导致子层数组为零。在Swift中,这会导致self.sublayers上的选项展开崩溃。(在Obj-C上可能没问题,因为[nil count]可能返回0,这实际上是可行的)。我完全忘记了zPosition,这个答案是最好的。这两个答案都有效,但从以下方面来看,这个答案更简单、更可靠:“在另一个子层的上方或下方插入时,您只需指定子层在子层数组中的位置。图层的实际可见性主要由其zPosition属性中的值决定,其次由其在子图层数组中的位置决定
let view = NSView(frame: ...)
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.gray.cgColor

let l1 = CALayer(...)
let l2 = CALayer(...)

view.layer?.addSublayer(l1)
view.layer?.addSublayer(l2)

l1.bringToFront()