CALayer's auto layout

Those who have used CALayer and its subclasses know that this device is very powerful, beautiful and takes up little memory
However, the most disgusting thing is that you need to calculate frame when you use it

AutoLayout only supports UIView and its subclasses. So, how can we make Layer have this feature
First of all, we need to know

1. There is a Layer on uiview
 2. The way to add layer is similar to uiview: 'layer addsublayer'
3. An Application must have at least one UIView(UIWindow)

We print the layer of UIView object and find that it is an instance of CALayer. Then, the layer of UIView is CALayer. We know that UIView supports automatic layout. Can we rewrite the method of creating layer of UIView to enable it to support automatic layout of corresponding layer soon

///apple documentation
This method returns the CALayer class object by default. Subclasses can override this method and return a different layer class as needed. For example, if your view uses tiling to display a large scrollable area, you might want to override this property and return the CATiledLayer class, as shown in Listing 1.

Let's use CAGradientLayer as an example to create a gradient View that supports automatic layout

///Rewrite the following method in GradientLayerView.m
+ (Class)layerClass {
    return [CAGradientLayer class];
}

When used

GradientLayerView *gradientView = [GradientLayerView new];
(CAGradientLayer)gradientView.layer.startPoint = CGPoint(x ,y);
......

It seems a little inconvenient

//.h
@interface CHGradientLayerView : UIView
@property (nonatomic, nullable, copy) NSArray *colors;
@property (nonatomic, nullable, copy) NSArray<NSNumber *> *locations;
@property (nonatomic, assign) CGPoint startPoint;
@property (nonatomic, assign) CGPoint endPoint;
@property (nonatomic ,copy) CAGradientLayerType type;
@end
//.m
@implementation CHGradientLayerView
#pragma mark getter
+ (Class)layerClass {
    return [CAGradientLayer class];
}
- (NSArray *)colors {
    return ((CAGradientLayer *)self.layer).colors;
}
- (NSArray<NSNumber *> *)locations {
    return ((CAGradientLayer *)self.layer).locations;
}
- (CGPoint)startPoint {
    return ((CAGradientLayer *)self.layer).startPoint;
}
- (CGPoint)endPoint {
    return ((CAGradientLayer *)self.layer).endPoint;
}
- (CAGradientLayerType)type {
    return ((CAGradientLayer *)self.layer).type;
}
#pragma mark setter
- (void)setColors:(NSArray *)colors {
    ((CAGradientLayer *)self.layer).colors = colors;
}
- (void)setLocations:(NSArray<NSNumber *> *)locations {
    ((CAGradientLayer *)self.layer).locations = locations;
}
- (void)setStartPoint:(CGPoint)startPoint {
    ((CAGradientLayer *)self.layer).startPoint = startPoint;
}
- (void)setEndPoint:(CGPoint)endPoint {
    ((CAGradientLayer *)self.layer).endPoint = endPoint;
}
- (void)setType:(CAGradientLayerType)type {
    ((CAGradientLayer *)self.layer).type = type;
}
@end

Use becomes

GradientLayerView *gradientView = [GradientLayerView new];
gradientView.startPoint = CGPoint(x ,y);
......

The automatic layout of the layer can be used at will. The memory consumption is not very large. Is it very comfortable? Other subclasses of CALayer can also be modified to support the automatic layout of LayerView
CHLayeView-Demo

Posted by surfinglight on Sat, 21 Dec 2019 07:20:08 -0800