How to draw lines using UIView? - ios

I can draw lines using CGContext. How to draw lines with the same coordinates using UIView? I want to move lines in the future, so that I need to use UIView.
func DrawLine()
{
UIGraphicsBeginImageContext(self.view.frame.size)
imageView.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
let context = UIGraphicsGetCurrentContext()
let lineWidth : CGFloat = 5
context?.move(to: CGPoint(x: 100, y: 100))
context?.addLine(to: CGPoint(x: self.view.frame.width - 100, y: 100))
context?.setBlendMode(CGBlendMode.normal)
context?.setLineCap(CGLineCap.round)
context?.setLineWidth(lineWidth)
context?.setStrokeColor(UIColor(red: 0, green: 0, blue: 0, alpha: 1.0).cgColor)
context?.strokePath()
context?.move(to: CGPoint(x: self.view.frame.width/2, y: 100))
context?.addLine(to: CGPoint(x: self.view.frame.width/2, y: 700))
context?.strokePath()
imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
override func viewDidLoad()
{
super.viewDidLoad()
DrawLine()
}

Add a CAShapeLayer to a UIView
let shapeLayer = CAShapeLayer()
view.layer.addSublayer(shapeLayer)
set the shapelayer path to the lines
shapeLayer.path = // some CGPath you create
See: https://stackoverflow.com/a/40556796/3937 for how to make a CGPath with lines.

Related

UIBezierPath does not change color and is not added to the view

There is an implementation like this:
class EllupseTest: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let views = MyView(frame: CGRect(x: 36.62, y: 77.54, width: 303.19, height: 495.93))
views.backgroundColor = .clear
views.rotate(degrees: 45.84)
view.addSubview(views)
}
}
class Ellipse: UIView {
override func draw(_ rect: CGRect) {
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 303.19, height: 495.93))
UIColor.cyan.setFill()
path.fill()
}
}
But if I want to change the color, the rectangle will be colored, not the ellipse itself (that's why I put views.backgroundColor = .clear for a while) How can I change the color of the ellipse itself, and not its rectangle?
I read that you can use PaintCode, but I don't understand how to add it to the view via view.addSubview (). How to add to a view
Here is the code from PaintCode
//// General Declarations
let context = UIGraphicsGetCurrentContext()!
//// Color Declarations
let color = UIColor(red: 1.000, green: 0.773, blue: 0.620, alpha: 1.000)
//// Oval Drawing
context.saveGState()
context.translateBy(x: 610, y: -139)
context.rotate(by: 90 * CGFloat.pi/180)
let ovalPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 314.87, height: 515.04))
color.setFill()
ovalPath.fill()
context.restoreGState()
I work with UIBezierPath for the first time)

Custom change color of cell bottom border

I need to change color of bottom cell in UICollectionView, in this question just I do this
I need set color to bottom cell like this
let border = CALayer()
let width = CGFloat(2.0)
border.borderColor = UIColor(red: 184/255, green: 215/255, blue: 215/255, alpha: 1).cgColor
border.frame = CGRect(x: 0, y: cell.frame.size.height - width, width: cell.frame.size.width, height: cell.frame.size.height)
border.borderWidth = width
cell.layer.addSublayer(border)
cell.layer.masksToBounds = true
Instead of trying to add it as a border, I would add two layers instead as it is much easier. Something like :
override func layoutSubviews() {
super.layoutSubviews()
backgroundShape = CAShapeLayer.init()
backPath = UIBezierPath.init(rect: self.bounds)// Use your path
backgroundShape.path = backPath.cgPath
backgroundShape.fillColor = UIColor.blue.cgColor//border color in your case
self.layer.addSublayer(backgroundShape)
foregroundShape = CAShapeLayer()
forgroundPath = UIBezierPath.init(rect: CGRect.init(x: 0, y: -20, width: self.bounds.width, height: self.bounds.height))// Use your path with a little negative y
foregroundShape.path = forgroundPath.cgPath
foregroundShape.fillColor = UIColor.yellow.cgColor//white in your case
self.layer.addSublayer(foregroundShape)
}
A detailed answer:
class BorderedCell: UICollectionViewCell{
var backgroundShape: CAShapeLayer!
var backPath: UIBezierPath!
var foregroundShape: CAShapeLayer!
var forgroundPath: UIBezierPath!
override func layoutSubviews() {
super.layoutSubviews()
backgroundShape = CAShapeLayer.init()
backPath = drawCurvedShape(with: 0)
backgroundShape.path = backPath.cgPath
backgroundShape.fillColor = UIColor(red:0.76, green:0.86, blue:0.86, alpha:1.0).cgColor
self.layer.addSublayer(backgroundShape)
foregroundShape = CAShapeLayer()
forgroundPath = drawCurvedShape(with: -8)
foregroundShape.path = forgroundPath.cgPath
foregroundShape.fillColor = UIColor.white.cgColor
self.layer.addSublayer(foregroundShape)
}
func drawCurvedShape(with startingY: CGFloat) -> UIBezierPath{
let path = UIBezierPath.init()
path.move(to: CGPoint.init(x: 0, y: startingY))
path.addLine(to: CGPoint.init(x: self.bounds.width, y: startingY))
path.addLine(to: CGPoint.init(x: self.bounds.width, y: self.bounds.height + startingY - 30))
path.addQuadCurve(to: CGPoint.init(x: self.bounds.width - 30, y: self.bounds.height + startingY), controlPoint: CGPoint.init(x: self.bounds.width, y: self.bounds.height + startingY))
path.addLine(to: CGPoint.init(x: 0, y: self.bounds.height + startingY))
path.addLine(to: CGPoint.init(x: 0, y: startingY))
path.close()
return path
}
}
Output:
I did not make the drawShape exactly to the shape you require, just to something that would serve the purpose.

Image in UIImage resize when draw on it

When I load a image to my UIImageView and would like draw on it. Then will change the ratio of the image. Can somebody tell me what is here the wrong?
Thanks
Before drawing
When you drawing
func drawLines(fromPoint:CGPoint,toPoint:CGPoint) {
UIGraphicsBeginImageContext(self.view.frame.size)
imageView.image?.draw(in: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
let context = UIGraphicsGetCurrentContext()
context?.move(to: CGPoint(x: fromPoint.x, y: fromPoint.y))
context?.addLine(to: CGPoint(x: toPoint.x, y: toPoint.y))
context?.setBlendMode(CGBlendMode.normal)
context?.setLineCap(CGLineCap.round)
context?.setLineWidth(brushSize)
context?.setStrokeColor(UIColor(red: red, green: green, blue: blue, alpha: opacityValue).cgColor)
context?.strokePath()
imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}

What would be equal in Swift to draw path/rect with a specific color

in Android (in Java) I could do something like this (here I tried to draw Triangle figure which is filled with different colors, first half with red color and second with green, also black stroke around Triangle figure:
#Override
public void onDraw(Canvas canvas) {
....
canvas.clipPath(pathBoundary); // triangle figure path
canvas.drawPath(pathBoundary, paintBlack); // draw black stroke around figure
canvas.drawRect(rectRed, paintRed); // fill first half with red color
canvas.drawRect(rectGreen, paintGreen); // fill second half with green color
in iOS I just learned how to draw Triangle figure with only one color, would like to also draw with two colors (like in Android)
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.60)
context.fillPath()
context.clip()
... how to draw path with specific color?
... how to draw rect with specific color?
You can do just like you do on Android: stroke the triangle path, set it as clipping path, stroke a rectangle in red, stroke a rectangle in green.
UIGraphicsBeginImageContext(CGSize(width: 200, height: 200))
let context = UIGraphicsGetCurrentContext()!
context.beginPath()
context.move(to: CGPoint(x: 100, y: 0))
context.addLine(to: CGPoint(x: 0, y: 200))
context.addLine(to: CGPoint(x: 200, y: 200))
context.closePath()
let path = context.path!
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
context.addPath(path)
context.clip()
context.setFillColor(UIColor.red.cgColor)
context.fill(CGRect(x: 0, y: 0, width: 200, height: 150))
context.setFillColor(UIColor.green.cgColor)
context.fill(CGRect(x: 0, y: 150, width: 200, height: 50))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
You can run the code above in a playground. In the right column hover over the last line (the one for image), click on the eye icon and you'll see a preview of the image that was drawn.
The way you do it is basically by drawing two different paths. Each with a different fill color. Here is an example:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
let leftAngle = atan(rect.maxY/rect.midX)
context.beginPath()
context.move(to: leftVertex)
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: topVertex)
context.closePath()
context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
context.fillPath()
let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)
context.beginPath()
context.move(to: smallLeftVertex)
context.addLine(to: topVertex)
context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
context.closePath()
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
context.fillPath()
}
There is some math to evaluate which would be the vertices of the inner (smaller) triangle.
Here is the result:
If you want you can try it in a playground:
//: Playground - noun: a place where people can play
import UIKit
class TriangleView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
let leftAngle = atan(rect.maxY/rect.midX)
context.beginPath()
context.move(to: leftVertex)
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: topVertex)
context.closePath()
context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
context.fillPath()
let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)
context.beginPath()
context.move(to: smallLeftVertex)
context.addLine(to: topVertex)
context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
context.closePath()
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
context.fillPath()
}
}
let triangle = TriangleView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
triangle.backgroundColor = .white
**
Edit:
**
You can also avoid to draw two overlapping triangles by using the clip feature of CGContext. In this case the code would look like this:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
var path = CGMutablePath()
path.move(to: leftVertex)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: topVertex)
path.closeSubpath()
context.addPath(path)
context.clip()
context.setFillColor(red: 1, green: 0, blue: 0, alpha: 1)
context.fill(CGRect(x: 0, y: 0, width: rect.width, height: rect.height/2))
context.setFillColor(red: 0, green: 1, blue: 0, alpha: 1)
context.fill(CGRect(x: 0, y: rect.midY, width: rect.width, height: rect.height/2))
}
In the first part of the code we create the triangle, we extract the path just drown in the context and we add it as clipping path. Then we can fill the two rectangles with the two different colours.
Hope this answers your question.

Adding inner shadow to top of UIView

I looked up but I couldn't find how I can add an inner shadow to UIView, only top (from top to bottom) for Swift. What is the best way add inner circle in Swift?
Edit: I've found some questions & answers on SO however they are either in obj-c or looks so complicated. I was just looking for a more Swifty way, if there is any
What I want to achieve:
Here's a pure Swift version that I whipped up:
public class EdgeShadowLayer: CAGradientLayer {
public enum Edge {
case Top
case Left
case Bottom
case Right
}
public init(forView view: UIView,
edge: Edge = Edge.Top,
shadowRadius radius: CGFloat = 20.0,
toColor: UIColor = UIColor.white,
fromColor: UIColor = UIColor.black) {
super.init()
self.colors = [fromColor.cgColor, toColor.cgColor]
self.shadowRadius = radius
let viewFrame = view.frame
switch edge {
case .Top:
startPoint = CGPoint(x: 0.5, y: 0.0)
endPoint = CGPoint(x: 0.5, y: 1.0)
self.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: shadowRadius)
case .Bottom:
startPoint = CGPoint(x: 0.5, y: 1.0)
endPoint = CGPoint(x: 0.5, y: 0.0)
self.frame = CGRect(x: 0.0, y: viewFrame.height - shadowRadius, width: viewFrame.width, height: shadowRadius)
case .Left:
startPoint = CGPoint(x: 0.0, y: 0.5)
endPoint = CGPoint(x: 1.0, y: 0.5)
self.frame = CGRect(x: 0.0, y: 0.0, width: shadowRadius, height: viewFrame.height)
case .Right:
startPoint = CGPoint(x: 1.0, y: 0.5)
endPoint = CGPoint(x: 0.0, y: 0.5)
self.frame = CGRect(x: viewFrame.width - shadowRadius, y: 0.0, width: shadowRadius, height: viewFrame.height)
}
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
To use it,
let topShadow = EdgeShadowLayer(forView: targetView, edge: .Top)
targetView.layer.addSublayer(topShadow)
Note that it defaults to a black-to-white gradient that's 20 points deep.
The full code, with a sample UIViewController that lets you toggle shadows on all four corners of a view, can be found at https://github.com/jrtibbetts/Tenebrae. I've also documented the EdgeShadowLayer pretty thoroughly.
I used implement inner shadow to UIView using Objective-C. I try to translate code into swift. Please forgive me for my poor swift syntax
you can call function below in UIView.didMoveToSuperview
func drawShadow() {
if nil == self.shadowLayer {
let size = self.frame.size
self.clipsToBounds = true
let layer: CALayer = CALayer()
layer.backgroundColor = UIColor.lightGrayColor().CGColor
layer.position = CGPointMake(size.width / 2, -size.height / 2 + 0.5)
layer.bounds = CGRectMake(0, 0, size.width, size.height)
layer.shadowColor = UIColor.darkGrayColor().CGColor
layer.shadowOffset = CGSizeMake(0.5, 0.5)
layer.shadowOpacity = 0.8
layer.shadowRadius = 5.0
self.shadowLayer = layer
self.layer.addSublayer(layer)
}
}
I tweaked the modification made by #anoop4real using clear as the toColor and made the interface more in-line with the shadow settings in CALayer, including defaults, with the exception of opacity, which is set to 0.0 by default. I went with a default of 0.6 since it looked the most natural.
extension UIView {
func addShadow(to edges: [UIRectEdge], radius: CGFloat = 3.0, opacity: Float = 0.6, color: CGColor = UIColor.black.cgColor) {
let fromColor = color
let toColor = UIColor.clear.cgColor
let viewFrame = self.frame
for edge in edges {
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [fromColor, toColor]
gradientLayer.opacity = opacity
switch edge {
case .top:
gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: radius)
case .bottom:
gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
gradientLayer.frame = CGRect(x: 0.0, y: viewFrame.height - radius, width: viewFrame.width, height: radius)
case .left:
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.frame = CGRect(x: 0.0, y: 0.0, width: radius, height: viewFrame.height)
case .right:
gradientLayer.startPoint = CGPoint(x: 1.0, y: 0.5)
gradientLayer.endPoint = CGPoint(x: 0.0, y: 0.5)
gradientLayer.frame = CGRect(x: viewFrame.width - radius, y: 0.0, width: radius, height: viewFrame.height)
default:
break
}
self.layer.addSublayer(gradientLayer)
}
}
func removeAllShadows() {
if let sublayers = self.layer.sublayers, !sublayers.isEmpty {
for sublayer in sublayers {
sublayer.removeFromSuperlayer()
}
}
}
}
The top view is the default settings, and the bottom uses a radius of 5.0 to show more clearly.
view1.addShadow([.top, .bottom, .left, .right])
view2.addShadow([.top, .bottom, .left, .right], radius: 5.0)
view2.backgroundColor = .orange
I updated #NRitH's answer and made an extension out of it also modified so that you can manipulate multiple edges in one go
usage
myview.addShadow(to: [.top,.bottom], radius: 15.0)
extension UIView{
func addShadow(to edges:[UIRectEdge], radius:CGFloat){
let toColor = UIColor(colorLiteralRed: 235.0/255.0, green: 235.0/255.0, blue: 235.0/255.0, alpha: 1.0)
let fromColor = UIColor(colorLiteralRed: 188.0/255.0, green: 188.0/255.0, blue: 188.0/255.0, alpha: 1.0)
// Set up its frame.
let viewFrame = self.frame
for edge in edges{
let gradientlayer = CAGradientLayer()
gradientlayer.colors = [fromColor.cgColor,toColor.cgColor]
gradientlayer.shadowRadius = radius
switch edge {
case UIRectEdge.top:
gradientlayer.startPoint = CGPoint(x: 0.5, y: 0.0)
gradientlayer.endPoint = CGPoint(x: 0.5, y: 1.0)
gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: viewFrame.width, height: gradientlayer.shadowRadius)
case UIRectEdge.bottom:
gradientlayer.startPoint = CGPoint(x: 0.5, y: 1.0)
gradientlayer.endPoint = CGPoint(x: 0.5, y: 0.0)
gradientlayer.frame = CGRect(x: 0.0, y: viewFrame.height - gradientlayer.shadowRadius, width: viewFrame.width, height: gradientlayer.shadowRadius)
case UIRectEdge.left:
gradientlayer.startPoint = CGPoint(x: 0.0, y: 0.5)
gradientlayer.endPoint = CGPoint(x: 1.0, y: 0.5)
gradientlayer.frame = CGRect(x: 0.0, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
case UIRectEdge.right:
gradientlayer.startPoint = CGPoint(x: 1.0, y: 0.5)
gradientlayer.endPoint = CGPoint(x: 0.0, y: 0.5)
gradientlayer.frame = CGRect(x: viewFrame.width - gradientlayer.shadowRadius, y: 0.0, width: gradientlayer.shadowRadius, height: viewFrame.height)
default:
break
}
self.layer.addSublayer(gradientlayer)
}
}
func removeAllSublayers(){
if let sublayers = self.layer.sublayers, !sublayers.isEmpty{
for sublayer in sublayers{
sublayer.removeFromSuperlayer()
}
}
}
}
Swift 5 extension
extension UIView {
func addInnerShadow() {
let innerShadow = CALayer()
innerShadow.frame = bounds
// Shadow path (1pt ring around bounds)
let radius = self.layer.cornerRadius
let path = UIBezierPath(roundedRect: innerShadow.bounds.insetBy(dx: 2, dy:2), cornerRadius:radius)
let cutout = UIBezierPath(roundedRect: innerShadow.bounds, cornerRadius:radius).reversing()
path.append(cutout)
innerShadow.shadowPath = path.cgPath
innerShadow.masksToBounds = true
// Shadow properties
innerShadow.shadowColor = UIColor.black.cgColor
innerShadow.shadowOffset = CGSize(width: 0, height: 0)
innerShadow.shadowOpacity = 0.5
innerShadow.shadowRadius = 2
innerShadow.cornerRadius = self.layer.cornerRadius
layer.addSublayer(innerShadow)
}
}
I rewrote #NRitH solution on Swift 3, also slightly refactor it:
final class SideShadowLayer: CAGradientLayer {
enum Side {
case top,
bottom,
left,
right
}
init(frame: CGRect, side: Side, shadowWidth: CGFloat,
fromColor: UIColor = .black,
toColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0),
opacity: Float = 0.5) {
super.init()
colors = [fromColor.cgColor, toColor.cgColor]
self.opacity = opacity
switch side {
case .bottom:
startPoint = CGPoint(x: 0.5, y: 1.0)
endPoint = CGPoint(x: 0.5, y: 0.0)
self.frame = CGRect(x: 0, y: frame.height - shadowWidth, width: frame.width, height: shadowWidth)
case .top:
startPoint = CGPoint(x: 0.5, y: 0.0)
endPoint = CGPoint(x: 0.5, y: 1.0)
self.frame = CGRect(x: 0, y: 0, width: frame.width, height: shadowWidth)
case .left:
startPoint = CGPoint(x: 0.0, y: 0.5)
endPoint = CGPoint(x: 1.0, y: 0.5)
self.frame = CGRect(x: 0, y: 0, width: shadowWidth, height: frame.height)
case .right:
startPoint = CGPoint(x: 1.0, y: 0.5)
endPoint = CGPoint(x: 0.0, y: 0.5)
self.frame = CGRect(x: frame.width - shadowWidth, y: 0, width: shadowWidth, height: frame.height)
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
If you don't mind using clipsToBounds = true, you can create a new CALayer offset just off the edge of your view and add the shadow to THAT view. This is what J.Hunter's answer does.
J.Hunter's code adds a top shadow, here I updated it to Swift 5 and added it to the bottom.
Swift 5:
override func draw(_ rect: CGRect) {
// Create Inner Shadow. Not sure about efficiency of this.
// You may want to create a shadowLayer property
// and only run this code if it hasn't been created yet.
let size = rect.size
clipsToBounds = true // Don't want to see your fake view layer
let innerShadowLayer: CALayer = CALayer()
// Need to set a backgroundColor or it doesn't work
innerShadowLayer.backgroundColor = UIColor.black.cgColor
// Position your shadow layer (anchor point is in the center)
// on the edge of where your shadow needs to be.
// In my case this moves the shadow layer to the
// bottom edge of my view
innerShadowLayer.position = CGPoint(x: size.width / 2, y: size.height + (size.height / 2))
// This could be smaller I think, just copying J.Hunter's code...
innerShadowLayer.bounds = CGRect(x: 0, y: 0, width: size.width, height: size.height)
// Normal shadow layer properties you'd use for an outer shadow
innerShadowLayer.shadowColor = UIColor.black.cgColor
innerShadowLayer.shadowOffset = CGSize(width: 0, height: 0)
innerShadowLayer.shadowOpacity = 0.3
innerShadowLayer.shadowRadius = 3
layer.addSublayer(innerShadowLayer)
}

Resources