Swift 扩展归纳--- UIView

这篇文章主要是记录下 UIView 的常用扩展,方便自己使用的时候寻找查看,将从以下基础操作几何操作、样式和外观、动画系统、手势处理、布局公布工具、视图管理、调试工具、高级效果、性能优化、使用工具等方面进行分类归纳。

1、Frame相关属性扩展

swift 复制代码
// MARK: - Frame相关属性扩展
extension UIView {
    /// 视图的x坐标
    /// - Note: 设置时会保持其他frame属性不变
    /// - Example:
    ///   ```
    ///   view.x = 100
    ///   print(view.x) // 100
    ///   ```
    var x: CGFloat {
        get { return frame.origin.x }
        set { frame.origin.x = newValue }
    }
    
    /// 视图的y坐标
    /// - Note: 设置时会保持其他frame属性不变
    /// - Example:
    ///   ```
    ///   view.y = 50
    ///   print(view.y) // 50
    ///   ```
    var y: CGFloat {
        get { return frame.origin.y }
        set { frame.origin.y = newValue }
    }
    
    /// 视图的宽度
    /// - Note: 设置时会保持origin不变
    /// - Example:
    ///   ```
    ///   view.width = 200
    ///   print(view.width) // 200
    ///   ```
    var width: CGFloat {
        get { return frame.size.width }
        set { frame.size.width = newValue }
    }
    
    /// 视图的高度
    /// - Note: 设置时会保持origin不变
    /// - Example:
    ///   ```
    ///   view.height = 300
    ///   print(view.height) // 300
    ///   ```
    var height: CGFloat {
        get { return frame.size.height }
        set { frame.size.height = newValue }
    }
    
    /// 视图的origin点
    /// - Note: 包含x和y坐标
    /// - Example:
    ///   ```
    ///   view.origin = CGPoint(x: 10, y: 20)
    ///   print(view.origin) // (10.0, 20.0)
    ///   ```
    var origin: CGPoint {
        get { return frame.origin }
        set { frame.origin = newValue }
    }
    
    /// 视图的size
    /// - Note: 包含宽度和高度
    /// - Example:
    ///   ```
    ///   view.size = CGSize(width: 100, height: 200)
    ///   print(view.size) // (100.0, 200.0)
    ///   ```
    var size: CGSize {
        get { return frame.size }
        set { frame.size = newValue }
    }
    
    /// 视图的中心点x坐标
    /// - Note: 基于父视图坐标系
    /// - Example:
    ///   ```
    ///   view.centerX = 150
    ///   print(view.centerX) // 150
    ///   ```
    var centerX: CGFloat {
        get { return center.x }
        set { center.x = newValue }
    }
    
    /// 视图的中心点y坐标
    /// - Note: 基于父视图坐标系
    /// - Example:
    ///   ```
    ///   view.centerY = 200
    ///   print(view.centerY) // 200
    ///   ```
    var centerY: CGFloat {
        get { return center.y }
        set { center.y = newValue }
    }
    
    /// 视图的右边界x坐标
    /// - Note: 等于x + width
    /// - Example:
    ///   ```
    ///   view.right = 300 // 会自动调整x坐标
    ///   print(view.right) // 300
    ///   ```
    var right: CGFloat {
        get { return frame.origin.x + frame.size.width }
        set { frame.origin.x = newValue - frame.size.width }
    }
    
    /// 视图的底边界y坐标
    /// - Note: 等于y + height
    /// - Example:
    ///   ```
    ///   view.bottom = 400 // 会自动调整y坐标
    ///   print(view.bottom) // 400
    ///   ```
    var bottom: CGFloat {
        get { return frame.origin.y + frame.size.height }
        set { frame.origin.y = newValue - frame.size.height }
    }
    
}

2、圆角和边框相关

swift 复制代码
// MARK: - 圆角和边框相关
extension UIView {
    /// 设置视图圆角
    /// - Parameter radius: 圆角半径
    /// - Note: 会自动设置clipsToBounds为true
    /// - Example:
    ///   ```
    ///   view.setCornerRadius(10)
    ///   ```
    func setCornerRadius(_ radius: CGFloat) {
        layer.cornerRadius = radius
        clipsToBounds = true
    }
    
    /// 设置视图边框
    /// - Parameters:
    ///   - width: 边框宽度
    ///   - color: 边框颜色
    /// - Example:
    ///   ```
    ///   view.setBorder(width: 2, color: .red)
    ///   ```
    func setBorder(width: CGFloat, color: UIColor) {
        layer.borderWidth = width
        layer.borderColor = color.cgColor
    }
    
    /// 设置视图阴影
    /// - Parameters:
    ///   - color: 阴影颜色
    ///   - opacity: 阴影透明度
    ///   - offset: 阴影偏移量
    ///   - radius: 阴影模糊半径
    /// - Example:
    ///   ```
    ///   view.setShadow(color: .black, opacity: 0.3, offset: CGSize(width: 2, height: 2), radius: 4)
    ///   ```
    func setShadow(color: UIColor, opacity: Float, offset: CGSize, radius: CGFloat) {
        layer.shadowColor = color.cgColor
        layer.shadowOpacity = opacity
        layer.shadowOffset = offset
        layer.shadowRadius = radius
        layer.masksToBounds = false
    }
    
    /// 同时设置圆角和阴影
    /// - Parameters:
    ///   - cornerRadius: 圆角半径
    ///   - shadowColor: 阴影颜色
    ///   - shadowOpacity: 阴影透明度
    ///   - shadowOffset: 阴影偏移量
    ///   - shadowRadius: 阴影模糊半径
    /// - Note: 使用容器视图解决圆角和阴影冲突问题
    /// - Example:
    ///   ```
    ///   view.setCornerRadiusWithShadow(
    ///       cornerRadius: 10,
    ///       shadowColor: .black,
    ///       shadowOpacity: 0.3,
    ///       shadowOffset: CGSize(width: 0, height: 2),
    ///       shadowRadius: 4
    ///   )
    ///   ```
    func setCornerRadiusWithShadow(cornerRadius: CGFloat,
                                   shadowColor: UIColor,
                                   shadowOpacity: Float,
                                   shadowOffset: CGSize,
                                   shadowRadius: CGFloat) {
        // 创建容器视图
        let containerView = UIView()
        containerView.frame = frame
        containerView.backgroundColor = UIColor.clear
        
        // 设置阴影
        containerView.layer.shadowColor = shadowColor.cgColor
        containerView.layer.shadowOpacity = shadowOpacity
        containerView.layer.shadowOffset = shadowOffset
        containerView.layer.shadowRadius = shadowRadius
        containerView.layer.masksToBounds = false
        
        // 设置圆角
        layer.cornerRadius = cornerRadius
        clipsToBounds = true
        
        // 调整frame
        frame = bounds
        
        // 添加到容器
        superview?.insertSubview(containerView, belowSubview: self)
        containerView.addSubview(self)
    }
}


// MARK: - 指定角圆角扩展
extension UIView {
    
    /// 设置指定角的圆角
    /// - Parameters:
    ///   - corners: 要设置圆角的角(可多选)
    ///   - radius: 圆角半径
    /// - Example:
    ///   ```
    ///   // 只设置顶部两个角为圆角
    ///   view.setRoundCorners([.topLeft, .topRight], radius: 16)
    ///
    ///   // 只设置左侧两个角为圆角
    ///   view.setRoundCorners([.topLeft, .bottomLeft], radius: 12)
    ///   ```
    func setRoundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(
            roundedRect: bounds,
            byRoundingCorners: corners,
            cornerRadii: CGSize(width: radius, height: radius)
        )
        
        let maskLayer = CAShapeLayer()
        maskLayer.path = path.cgPath
        layer.mask = maskLayer
    }
    
    /// 设置指定角的圆角(支持不同半径)
    /// - Parameters:
    ///   - topLeft: 左上角半径
    ///   - topRight: 右上角半径
    ///   - bottomLeft: 左下角半径
    ///   - bottomRight: 右下角半径
    /// - Example:
    ///   ```
    ///   // 每个角设置不同的圆角半径
    ///   view.setRoundCorners(topLeft: 16, topRight: 16, bottomLeft: 0, bottomRight: 0)
    ///   ```
    func setRoundCorners(topLeft: CGFloat = 0,
                     topRight: CGFloat = 0,
                     bottomLeft: CGFloat = 0,
                     bottomRight: CGFloat = 0) {
        
        let path = UIBezierPath()
        let width = bounds.width
        let height = bounds.height
        
        // 从左上角开始,顺时针绘制路径
        path.move(to: CGPoint(x: topLeft, y: 0))
        
        // 顶边
        path.addLine(to: CGPoint(x: width - topRight, y: 0))
        
        // 右上角
        if topRight > 0 {
            path.addArc(withCenter: CGPoint(x: width - topRight, y: topRight),
                       radius: topRight,
                       startAngle: -CGFloat.pi/2,
                       endAngle: 0,
                       clockwise: true)
        }
        
        // 右边
        path.addLine(to: CGPoint(x: width, y: height - bottomRight))
        
        // 右下角
        if bottomRight > 0 {
            path.addArc(withCenter: CGPoint(x: width - bottomRight, y: height - bottomRight),
                       radius: bottomRight,
                       startAngle: 0,
                       endAngle: CGFloat.pi/2,
                       clockwise: true)
        }
        
        // 底边
        path.addLine(to: CGPoint(x: bottomLeft, y: height))
        
        // 左下角
        if bottomLeft > 0 {
            path.addArc(withCenter: CGPoint(x: bottomLeft, y: height - bottomLeft),
                       radius: bottomLeft,
                       startAngle: CGFloat.pi/2,
                       endAngle: CGFloat.pi,
                       clockwise: true)
        }
        
        // 左边
        path.addLine(to: CGPoint(x: 0, y: topLeft))
        
        // 左上角
        if topLeft > 0 {
            path.addArc(withCenter: CGPoint(x: topLeft, y: topLeft),
                       radius: topLeft,
                       startAngle: CGFloat.pi,
                       endAngle: -CGFloat.pi/2,
                       clockwise: true)
        }
        
        path.close()
        
        let maskLayer = CAShapeLayer()
        maskLayer.path = path.cgPath
        layer.mask = maskLayer
    }
    
    /// 使用CACornerMask设置指定角圆角(iOS 11+)
    /// - Parameters:
    ///   - corners: 要设置圆角的角
    ///   - radius: 圆角半径
    /// - Example:
    ///   ```
    ///   // 使用更高效的方式设置圆角(iOS 11+)
    ///   view.setRoundCorners(corners: [.layerMinXMinYCorner, .layerMaxXMinYCorner], radius: 16)
    ///   ```
    @available(iOS 11.0, *)
    func setRoundCorners(corners: CACornerMask, radius: CGFloat) {
        layer.cornerRadius = radius
        layer.maskedCorners = corners
        clipsToBounds = true
    }
    
    /// 设置顶部圆角
    /// - Parameter radius: 圆角半径
    /// - Example:
    ///   ```
    ///   headerView.setRoundTopCorners(radius: 16)
    ///   ```
    func setRoundTopCorners(radius: CGFloat) {
        if #available(iOS 11.0, *) {
            setRoundCorners(corners: [.layerMinXMinYCorner, .layerMaxXMinYCorner], radius: radius)
        } else {
            setRoundCorners([.topLeft, .topRight], radius: radius)
        }
    }
    
    /// 设置底部圆角
    /// - Parameter radius: 圆角半径
    /// - Example:
    ///   ```
    ///   footerView.setRoundBottomCorners(radius: 16)
    ///   ```
    func setRoundBottomCorners(radius: CGFloat) {
        if #available(iOS 11.0, *) {
            setRoundCorners(corners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner], radius: radius)
        } else {
            setRoundCorners([.bottomLeft, .bottomRight], radius: radius)
        }
    }
    
    /// 设置左侧圆角
    /// - Parameter radius: 圆角半径
    /// - Example:
    ///   ```
    ///   leftPanelView.setRoundLeftCorners(radius: 12)
    ///   ```
    func setRoundLeftCorners(radius: CGFloat) {
        if #available(iOS 11.0, *) {
            setRoundCorners(corners: [.layerMinXMinYCorner, .layerMinXMaxYCorner], radius: radius)
        } else {
            setRoundCorners([.topLeft, .bottomLeft], radius: radius)
        }
    }
    
    /// 设置右侧圆角
    /// - Parameter radius: 圆角半径
    /// - Example:
    ///   ```
    ///   rightPanelView.setRoundRightCorners(radius: 12)
    ///   ```
    func setRoundRightCorners(radius: CGFloat) {
        if #available(iOS 11.0, *) {
            setRoundCorners(corners: [.layerMaxXMinYCorner, .layerMaxXMaxYCorner], radius: radius)
        } else {
            setRoundCorners([.topRight, .bottomRight], radius: radius)
        }
    }
    
    /// 移除圆角mask(恢复原始形状)
    /// - Example:
    ///   ```
    ///   view.removeCornerRadius()
    ///   ```
    func removeCornerRadius() {
        layer.mask = nil
        layer.cornerRadius = 0
        if #available(iOS 11.0, *) {
            layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner,
                                   .layerMinXMaxYCorner, .layerMaxXMaxYCorner]
        }
    }
}

3、渐变背景相关

swift 复制代码
// MARK: - 渐变背景相关
extension UIView {
    /// 设置线性渐变背景
    /// - Parameters:
    ///   - colors: 渐变颜色数组
    ///   - startPoint: 起始点 (0,0)到(1,1)
    ///   - endPoint: 结束点 (0,0)到(1,1)
    /// - Example:
    ///   ```
    ///   view.setGradientBackground(
    ///       colors: [UIColor.red, UIColor.blue],
    ///       startPoint: CGPoint(x: 0, y: 0),
    ///       endPoint: CGPoint(x: 1, y: 1)
    ///   )
    ///   ```
    func setGradientBackground(colors: [UIColor], startPoint: CGPoint, endPoint: CGPoint) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
        gradientLayer.frame = bounds
        
        layer.sublayers?.removeAll { $0 is CAGradientLayer }
        layer.insertSublayer(gradientLayer, at: 0)
    }
    
    /// 设置径向渐变背景
    /// - Parameters:
    ///   - colors: 渐变颜色数组
    ///   - center: 渐变中心点
    ///   - radius: 渐变半径
    /// - Example:
    ///   ```
    ///   view.setRadialGradientBackground(
    ///       colors: [UIColor.white, UIColor.black],
    ///       center: CGPoint(x: 0.5, y: 0.5),
    ///       radius: 100
    ///   )
    ///   ```
    func setRadialGradientBackground(colors: [UIColor], center: CGPoint, radius: CGFloat) {
        let gradientLayer = CAGradientLayer()
        gradientLayer.type = .radial
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.startPoint = center
        gradientLayer.endPoint = CGPoint(x: center.x + radius / bounds.width, y: center.y + radius / bounds.height)
        gradientLayer.frame = bounds
        
        layer.sublayers?.removeAll { $0 is CAGradientLayer }
        layer.insertSublayer(gradientLayer, at: 0)
    }
    
}

4、动画相关

swift 复制代码
// MARK: - 动画相关
extension UIView {
    /// 淡入动画
    /// - Parameters:
    ///   - duration: 动画时长
    ///   - completion: 完成回调
    /// - Example:
    ///   ```
    ///   view.fadeIn(duration: 0.3) {
    ///       print("淡入动画完成")
    ///   }
    ///   ```
    func fadeIn(duration: TimeInterval = 0.3, completion: (() -> Void)? = nil) {
        alpha = 0
        UIView.animate(withDuration: duration, animations: {
            self.alpha = 1
        }) { _ in
            completion?()
        }
    }
    
    /// 淡出动画
    /// - Parameters:
    ///   - duration: 动画时长
    ///   - completion: 完成回调
    /// - Example:
    ///   ```
    ///   view.fadeOut(duration: 0.3) {
    ///       print("淡出动画完成")
    ///   }
    ///   ```
    func fadeOut(duration: TimeInterval = 0.3, completion: (() -> Void)? = nil) {
        UIView.animate(withDuration: duration, animations: {
            self.alpha = 0
        }) { _ in
            completion?()
        }
    }
    
    /// 缩放动画
    /// - Parameters:
    ///   - scale: 缩放比例
    ///   - duration: 动画时长
    ///   - completion: 完成回调
    /// - Example:
    ///   ```
    ///   view.scale(to: 1.5, duration: 0.3) {
    ///       print("缩放动画完成")
    ///   }
    ///   ```
    func scale(to scale: CGFloat, duration: TimeInterval = 0.3, completion: (() -> Void)? = nil) {
        UIView.animate(withDuration: duration, animations: {
            self.transform = CGAffineTransform(scaleX: scale, y: scale)
        }) { _ in
            completion?()
        }
    }
    
    /// 弹簧动画
    /// - Parameters:
    ///   - damping: 阻尼比例 (0.0 - 1.0)
    ///   - velocity: 初始速度
    ///   - duration: 动画时长
    ///   - animations: 动画操作
    ///   - completion: 完成回调
    /// - Example:
    ///   ```
    ///   view.springAnimation(damping: 0.7, velocity: 0.5, duration: 0.5, animations: {
    ///       view.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
    ///   })
    ///   ```
    func springAnimation(damping: CGFloat = 0.7,
                         velocity: CGFloat = 0.5,
                         duration: TimeInterval = 0.5,
                         animations: @escaping () -> Void,
                         completion: (() -> Void)? = nil) {
        UIView.animate(withDuration: duration,
                       delay: 0,
                       usingSpringWithDamping: damping,
                       initialSpringVelocity: velocity,
                       options: .curveEaseInOut,
                       animations: animations) { _ in
            completion?()
        }
    }
    
    /// 震动动画
    /// - Parameters:
    ///   - intensity: 震动强度
    ///   - duration: 动画时长
    /// - Example:
    ///   ```
    ///   view.shake(intensity: 10, duration: 0.5)
    ///   ```
    func shake(intensity: CGFloat = 10, duration: TimeInterval = 0.5) {
        let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
        animation.timingFunction = CAMediaTimingFunction(name: .linear)
        animation.duration = duration
        animation.values = [-intensity, intensity, -intensity, intensity, -intensity/2, intensity/2, -intensity/4, intensity/4, 0]
        layer.add(animation, forKey: "shake")
    }
    
    /// 旋转动画
    /// - Parameters:
    ///   - angle: 旋转角度 (弧度)
    ///   - duration: 动画时长
    ///   - completion: 完成回调
    /// - Example:
    ///   ```
    ///   view.rotate(angle: .pi, duration: 1.0) {
    ///       print("旋转动画完成")
    ///   }
    ///   ```
    func rotate(angle: CGFloat, duration: TimeInterval = 1.0, completion: (() -> Void)? = nil) {
        UIView.animate(withDuration: duration, animations: {
            self.transform = self.transform.rotated(by: angle)
        }) { _ in
            completion?()
        }
    }
    
    /// 无限旋转动画
    /// - Parameters:
    ///   - duration: 一圈的时长
    ///   - clockwise: 是否顺时针
    /// - Example:
    ///   ```
    ///   view.startRotating(duration: 2.0, clockwise: true)
    ///   // 停止旋转
    ///   view.stopRotating()
    ///   ```
    func startRotating(duration: TimeInterval = 2.0, clockwise: Bool = true) {
        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
        rotationAnimation.fromValue = 0
        rotationAnimation.toValue = clockwise ? CGFloat.pi * 2 : -CGFloat.pi * 2
        rotationAnimation.duration = duration
        rotationAnimation.repeatCount = Float.infinity
        layer.add(rotationAnimation, forKey: "rotationAnimation")
    }
    
    /// 停止旋转动画
    /// - Example:
    ///   ```
    ///   view.stopRotating()
    ///   ```
    func stopRotating() {
        layer.removeAnimation(forKey: "rotationAnimation")
    }
    
}

5、视图层次相关

swift 复制代码
// MARK: - 视图层次相关
extension UIView {
    /// 移除所有子视图
    /// - Example:
    ///   ```
    ///   containerView.removeAllSubviews()
    ///   ```
    func removeAllSubviews() {
        subviews.forEach { $0.removeFromSuperview() }
    }
    
    /// 添加多个子视图
    /// - Parameter subviews: 子视图数组
    /// - Example:
    ///   ```
    ///   containerView.addSubviews([label, button, imageView])
    ///   ```
    func addSubviews(_ subviews: [UIView]) {
        subviews.forEach { addSubview($0) }
    }
    
    /// 获取指定类型的父视图
    /// - Parameter type: 父视图类型
    /// - Returns: 指定类型的父视图,如果没有找到返回nil
    /// - Example:
    ///   ```
    ///   if let tableView = view.parentView(of: UITableView.self) {
    ///       print("找到父级TableView")
    ///   }
    ///   ```
    func parentView<T: UIView>(of type: T.Type) -> T? {
        var currentView = superview
        while currentView != nil {
            if let targetView = currentView as? T {
                return targetView
            }
            currentView = currentView?.superview
        }
        return nil
    }
    
    /// 获取所有指定类型的子视图
    /// - Parameter type: 子视图类型
    /// - Returns: 指定类型的子视图数组
    /// - Example:
    ///   ```
    ///   let allLabels = containerView.subviews(of: UILabel.self)
    ///   print("找到 \(allLabels.count) 个标签")
    ///   ```
    func subviews<T: UIView>(of type: T.Type) -> [T] {
        var result: [T] = []
        for subview in subviews {
            if let targetView = subview as? T {
                result.append(targetView)
            }
            result.append(contentsOf: subview.subviews(of: type))
        }
        return result
    }
    
    /// 将视图移到最前面
    /// - Example:
    ///   ```
    ///   view.bringToFront()
    ///   ```
    func bringToFront() {
        superview?.bringSubviewToFront(self)
    }
    
    /// 将视图移到最后面
    /// - Example:
    ///   ```
    ///   view.sendToBack()
    ///   ```
    func sendToBack() {
        superview?.sendSubviewToBack(self)
    }
    // MARK: - 视图查找相关
extension UIView {
    /// 通过tag查找子视图
    /// - Parameter tag: 视图tag
    /// - Returns: 找到的视图,如果没有找到返回nil
    /// - Example:
    ///   ```
    ///   if let targetView = containerView.findSubview(withTag: 100) {
    ///       targetView.isHidden = true
    ///   }
    ///   ```
    func findSubview(withTag tag: Int) -> UIView? {
        return viewWithTag(tag)
    }
    
    /// 递归查找指定类型的第一个子视图
    /// - Parameter type: 视图类型
    /// - Returns: 找到的视图,如果没有找到返回nil
    /// - Example:
    ///   ```
    ///   if let button = containerView.findFirstSubview(of: UIButton.self) {
    ///       button.isEnabled = false
    ///   }
    ///   ```
    func findFirstSubview<T: UIView>(of type: T.Type) -> T? {
        for subview in subviews {
            if let targetView = subview as? T {
                return targetView
            }
            if let found = subview.findFirstSubview(of: type) {
                return found
            }
        }
        return nil
    }
}
}

6、截图和图像相关

swift 复制代码
// MARK: - 截图和图像相关
extension UIView {
    /// 截取视图截图
    /// - Returns: 视图的截图
    /// - Example:
    ///   ```
    ///   let screenshot = view.takeScreenshot()
    ///   imageView.image = screenshot
    ///   ```
    func takeScreenshot() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale)
        defer { UIGraphicsEndImageContext() }
        
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        layer.render(in: context)
        
        return UIGraphicsGetImageFromCurrentImageContext()
    }
    
    /// 截取视图指定区域的截图
    /// - Parameter rect: 截图区域
    /// - Returns: 指定区域的截图
    /// - Example:
    ///   ```
    ///   let cropRect = CGRect(x: 0, y: 0, width: 100, height: 100)
    ///   let croppedImage = view.takeScreenshot(in: cropRect)
    ///   ```
    func takeScreenshot(in rect: CGRect) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
        defer { UIGraphicsEndImageContext() }
        
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        context.translateBy(x: -rect.origin.x, y: -rect.origin.y)
        layer.render(in: context)
        
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

7、约束相关扩展

swift 复制代码
// MARK: - 约束相关扩展
extension UIView {
    /// 设置视图相对于父视图的约束
    /// - Parameters:
    ///   - top: 顶部边距
    ///   - left: 左边边距
    ///   - bottom: 底部边距
    ///   - right: 右边边距
    /// - Note: 使用Auto Layout,确保translatesAutoresizingMaskIntoConstraints = false
    /// - Example:
    ///   ```
    ///   view.pinToSuperview(top: 20, left: 16, bottom: 20, right: 16)
    ///   ```
    func pinToSuperview(top: CGFloat? = nil,
                        left: CGFloat? = nil,
                        bottom: CGFloat? = nil,
                        right: CGFloat? = nil) {
        guard let superview = superview else { return }
        
        translatesAutoresizingMaskIntoConstraints = false
        
        if let top = top {
            topAnchor.constraint(equalTo: superview.topAnchor, constant: top).isActive = true
        }
        if let left = left {
            leadingAnchor.constraint(equalTo: superview.leadingAnchor, constant: left).isActive = true
        }
        if let bottom = bottom {
            superview.bottomAnchor.constraint(equalTo: bottomAnchor, constant: bottom).isActive = true
        }
        if let right = right {
            superview.trailingAnchor.constraint(equalTo: trailingAnchor, constant: right).isActive = true
        }
    }
    
    /// 设置视图尺寸约束
    /// - Parameters:
    ///   - width: 宽度
    ///   - height: 高度
    /// - Example:
    ///   ```
    ///   view.setSize(width: 100, height: 200)
    ///   ```
    func setSize(width: CGFloat? = nil, height: CGFloat? = nil) {
        translatesAutoresizingMaskIntoConstraints = false
        
        if let width = width {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }
        if let height = height {
            heightAnchor.constraint(equalToConstant: height).isActive = true
        }
    }
    
    /// 设置视图居中约束
    /// - Parameters:
    ///   - centerX: 是否水平居中
    ///   - centerY: 是否垂直居中
    ///   - offsetX: 水平偏移量
    ///   - offsetY: 垂直偏移量
    /// - Example:
    ///   ```
    ///   view.centerInSuperview(centerX: true, centerY: true, offsetX: 10, offsetY: -5)
    ///   ```
    func centerInSuperview(centerX: Bool = false,
                           centerY: Bool = false,
                           offsetX: CGFloat = 0,
                           offsetY: CGFloat = 0) {
        guard let superview = superview else { return }
        
        translatesAutoresizingMaskIntoConstraints = false
        
        if centerX {
            centerXAnchor.constraint(equalTo: superview.centerXAnchor, constant: offsetX).isActive = true
        }
        if centerY {
            centerYAnchor.constraint(equalTo: superview.centerYAnchor, constant: offsetY).isActive = true
        }
    }
}

8、手势相关扩展

swift 复制代码
// MARK: - 手势相关扩展

extension UIView {
// MARK: - 私有方法和关联对象

    public struct AssociatedKeys {
        static var tapAction = "tapAction"
        static var longPressAction = "longPressAction"
        static var panAction = "panAction"
    }
    /// 添加点击手势
    /// - Parameter action: 点击回调
    /// - Example:
    ///   ```
    ///   view.addTapGesture {
    ///       print("视图被点击了")
    ///   }
    ///   ```
    func addTapGesture(_ action: @escaping () -> Void) {
        isUserInteractionEnabled = true
        let tapGesture = UITapGestureRecognizer()
        tapGesture.addTarget(self, action: #selector(handleTapGesture(_:)))
        addGestureRecognizer(tapGesture)
        
        objc_setAssociatedObject(self, &AssociatedKeys.tapAction, action, .OBJC_ASSOCIATION_COPY_NONATOMIC)
    }
    
    /// 添加长按手势
    /// - Parameters:
    ///   - minimumPressDuration: 最小按压时长
    ///   - action: 长按回调
    /// - Example:
    ///   ```
    ///   view.addLongPressGesture(minimumPressDuration: 1.0) {
    ///       print("视图被长按了")
    ///   }
    ///   ```
    func addLongPressGesture(minimumPressDuration: TimeInterval = 0.5, _ action: @escaping () -> Void) {
        isUserInteractionEnabled = true
        let longPressGesture = UILongPressGestureRecognizer()
        longPressGesture.minimumPressDuration = minimumPressDuration
        longPressGesture.addTarget(self, action: #selector(handleLongPressGesture(_:)))
        addGestureRecognizer(longPressGesture)
        
        objc_setAssociatedObject(self, &AssociatedKeys.longPressAction, action, .OBJC_ASSOCIATION_COPY_NONATOMIC)
    }
    
    /// 添加拖拽手势
    /// - Parameter action: 拖拽回调,参数为拖拽手势识别器
    /// - Example:
    ///   ```
    ///   view.addPanGesture { panGesture in
    ///       let translation = panGesture.translation(in: self.superview)
    ///       view.center = CGPoint(x: view.center.x + translation.x, y: view.center.y + translation.y)
    ///       panGesture.setTranslation(.zero, in: self.superview)
    ///   }
    ///   ```
    func addPanGesture(_ action: @escaping (UIPanGestureRecognizer) -> Void) {
        isUserInteractionEnabled = true
        let panGesture = UIPanGestureRecognizer()
        panGesture.addTarget(self, action: #selector(handlePanGesture(_:)))
        addGestureRecognizer(panGesture)
        
        objc_setAssociatedObject(self, &AssociatedKeys.panAction, action, .OBJC_ASSOCIATION_COPY_NONATOMIC)
    }
    
}

9、安全区域相关 (iOS 11+)

swift 复制代码
// MARK: - 安全区域相关 (iOS 11+)
extension UIView {
    /// 获取安全区域边距
    /// - Returns: 安全区域边距
    /// - Example:
    ///   ```
    ///   let safeInsets = view.safeAreaLayoutMargins
    ///   print("Top safe area: \(safeInsets.top)")
    ///   ```
    @available(iOS 11.0, *)
    var safeAreaLayoutMargins: UIEdgeInsets {
        return safeAreaInsets
    }
    
    /// 将视图固定到安全区域
    /// - Parameters:
    ///   - top: 顶部边距
    ///   - leading: 左边边距
    ///   - bottom: 底部边距
    ///   - trailing: 右边边距
    /// - Example:
    ///   ```
    ///   view.pinToSafeArea(top: 20, leading: 16, bottom: 20, trailing: 16)
    ///   ```
    @available(iOS 11.0, *)
    func pinToSafeArea(top: CGFloat? = nil,
                       leading: CGFloat? = nil,
                       bottom: CGFloat? = nil,
                       trailing: CGFloat? = nil) {
        guard let superview = superview else { return }
        
        translatesAutoresizingMaskIntoConstraints = false
        
        if let top = top {
            topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor, constant: top).isActive = true
        }
        if let leading = leading {
            leadingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leadingAnchor, constant: leading).isActive = true
        }
        if let bottom = bottom {
            superview.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor, constant: bottom).isActive = true
        }
        if let trailing = trailing {
            superview.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor, constant: trailing).isActive = true
        }
    }    
}

10、 工具方法

swift 复制代码
// MARK: - 工具方法
extension UIView {
    /// 检查视图是否完全可见
    /// - Returns: 是否完全可见
    /// - Example:
    ///   ```
    ///   if view.isCompletelyVisible {
    ///       print("视图完全可见")
    ///   }
    ///   ```
    var isCompletelyVisible: Bool {
        guard let superview = superview,
              let window = window else { return false }
        
        let viewFrameInWindow = superview.convert(frame, to: window)
        return window.bounds.contains(viewFrameInWindow)
    }
    
    /// 获取视图的响应链
    /// - Returns: 响应链数组
    /// - Example:
    ///   ```
    ///   let chain = view.responderChain
    ///   chain.forEach { print(type(of: $0)) }
    ///   ```
    var responderChain: [UIResponder] {
        var chain: [UIResponder] = [self]
        var current: UIResponder? = self
        
        while let next = current?.next {
            chain.append(next)
            current = next
        }
        
        return chain
    }
    
    /// 将点转换为其他视图的坐标系
    /// - Parameters:
    ///   - point: 原始点
    ///   - view: 目标视图
    /// - Returns: 转换后的点
    /// - Example:
    ///   ```
    ///   let pointInOtherView = view.convert(point: CGPoint(x: 10, y: 10), to: otherView)
    ///   ```
    func convert(point: CGPoint, to view: UIView?) -> CGPoint {
        return convert(point, to: view)
    }
    
    /// 检查点是否在视图内
    /// - Parameter point: 要检查的点
    /// - Returns: 是否在视图内
    /// - Example:
    ///   ```
    ///   let touchPoint = CGPoint(x: 50, y: 50)
    ///   if view.contains(point: touchPoint) {
    ///       print("点在视图内")
    ///   }
    ///   ```
    func contains(point: CGPoint) -> Bool {
        return bounds.contains(point)
    }
    
    /// 检查两个视图是否重叠
    /// - Parameter otherView: 另一个视图
    /// - Returns: 是否重叠
    /// - Example:
    ///   ```
    ///   if view1.isOverlapping(with: view2) {
    ///       print("两个视图重叠了")
    ///   }
    ///   ```
    func isOverlapping(with otherView: UIView) -> Bool {
        guard let superview = superview,
              let otherSuperview = otherView.superview,
              superview == otherSuperview else { return false }

        return frame.intersects(otherView.frame)
    }

    /// 计算两个视图的重叠区域
    /// - Parameter otherView: 另一个视图
    /// - Returns: 重叠区域,如果不重叠返回nil
    /// - Example:
    ///   ```
    ///   if let overlapRect = view1.overlapArea(with: view2) {
    ///       print("重叠区域: \(overlapRect)")
    ///   }
    ///   ```
    func overlapArea(with otherView: UIView) -> CGRect? {
        guard let superview = superview,
              let otherSuperview = otherView.superview,
              superview == otherSuperview else { return nil }

        let intersection = frame.intersection(otherView.frame)
        return intersection.isNull ? nil : intersection
    }
    
    /// 创建分隔线视图
    /// - Parameters:
    ///   - color: 分隔线颜色
    ///   - thickness: 分隔线厚度
    ///   - horizontal: 是否为水平分隔线
    /// - Returns: 分隔线视图
    /// - Example:
    ///   ```
    ///   let separator = UIView.createSeparator(color: .lightGray, thickness: 1, horizontal: true)
    ///   containerView.addSubview(separator)
    ///   ```
    static func createSeparator(color: UIColor = .lightGray,
                               thickness: CGFloat = 1,
                               horizontal: Bool = true) -> UIView {
        let separator = UIView()
        separator.backgroundColor = color
        separator.translatesAutoresizingMaskIntoConstraints = false
        
        if horizontal {
            separator.heightAnchor.constraint(equalToConstant: thickness).isActive = true
        } else {
            separator.widthAnchor.constraint(equalToConstant: thickness).isActive = true
        }
        
        return separator
    }
    
    /// 创建间距视图
    /// - Parameters:
    ///   - width: 宽度
    ///   - height: 高度
    /// - Returns: 间距视图
    /// - Example:
    ///   ```
    ///   let spacer = UIView.createSpacer(width: 20, height: 10)
    ///   stackView.addArrangedSubview(spacer)
    ///   ```
    static func createSpacer(width: CGFloat = 0, height: CGFloat = 0) -> UIView {
        let spacer = UIView()
        spacer.backgroundColor = .clear
        spacer.translatesAutoresizingMaskIntoConstraints = false
        
        if width > 0 {
            spacer.widthAnchor.constraint(equalToConstant: width).isActive = true
        }
        if height > 0 {
            spacer.heightAnchor.constraint(equalToConstant: height).isActive = true
        }
        
        return spacer
    }
    
    /// 获取当前视图控制器
    /// - Returns: 当前视图控制器
    /// - Example:
    ///   ```
    ///   if let currentVC = view.currentViewController {
    ///       currentVC.present(alertController, animated: true)
    ///   }
    ///   ```
    var currentViewController: UIViewController? {
        var responder = next
        while responder != nil {
            if let viewController = responder as? UIViewController {
                return viewController
            }
            responder = responder?.next
        }
        return nil
    }
}

11、额外的几何计算扩展

swift 复制代码
// MARK: - 额外的几何计算扩展
extension UIView {

    /// 视图的对角线长度
    /// - Returns: 对角线长度
    /// - Example:
    ///   ```
    ///   let diagonal = view.diagonalLength
    ///   print("对角线长度: \(diagonal)")
    ///   ```
    var diagonalLength: CGFloat {
        return sqrt(width * width + height * height)
    }

    /// 视图的面积
    /// - Returns: 视图面积
    /// - Example:
    ///   ```
    ///   let area = view.area
    ///   print("视图面积: \(area)")
    ///   ```
    var area: CGFloat {
        return width * height
    }

    /// 视图的周长
    /// - Returns: 视图周长
    /// - Example:
    ///   ```
    ///   let perimeter = view.perimeter
    ///   print("视图周长: \(perimeter)")
    ///   ```
    var perimeter: CGFloat {
        return 2 * (width + height)
    }

    /// 获取视图的四个角的坐标点
    /// - Returns: 包含四个角坐标的数组 [左上, 右上, 右下, 左下]
    /// - Example:
    ///   ```
    ///   let corners = view.cornerPoints
    ///   print("左上角: \(corners[0])")
    ///   ```
    var cornerPoints: [CGPoint] {
        return [
            CGPoint(x: x, y: y),           // 左上
            CGPoint(x: right, y: y),       // 右上
            CGPoint(x: right, y: bottom),  // 右下
            CGPoint(x: x, y: bottom)       // 左下
        ]
    }
}

12、状态相关扩展

swift 复制代码
// MARK: - 状态相关扩展
extension UIView {

    /// 视图是否真正可见(不仅仅是hidden=false)
    /// - Returns: 是否真正可见
    /// - Note: 检查alpha、hidden、superview等因素
    /// - Example:
    ///   ```
    ///   if view.isActuallyVisible {
    ///       print("视图真正可见")
    ///   }
    ///   ```
    var isActuallyVisible: Bool {
        return !isHidden && alpha > 0 && superview != nil && window != nil
    }

    /// 切换视图的显示/隐藏状态
    /// - Parameter animated: 是否使用动画
    /// - Example:
    ///   ```
    ///   view.toggleVisibility(animated: true)
    ///   ```
    func toggleVisibility(animated: Bool = false) {
        if animated {
            if isHidden {
                isHidden = false
                fadeIn()
            } else {
                fadeOut { [weak self] in
                    self?.isHidden = true
                    self?.alpha = 1 // 重置alpha以备下次显示
                }
            }
        } else {
            isHidden.toggle()
        }
    }

    /// 设置视图启用/禁用状态(包括所有子视图)
    /// - Parameters:
    ///   - enabled: 是否启用
    ///   - alpha: 禁用时的透明度
    /// - Example:
    ///   ```
    ///   containerView.setEnabled(false, alpha: 0.5)
    ///   ```
    func setEnabled(_ enabled: Bool, alpha: CGFloat = 0.5) {
        isUserInteractionEnabled = enabled
        self.alpha = enabled ? 1.0 : alpha

        subviews.forEach { subview in
            if let control = subview as? UIControl {
                control.isEnabled = enabled
            } else {
                subview.setEnabled(enabled, alpha: alpha)
            }
        }
    }
}

13、主题和样式相关扩展

swift 复制代码
// MARK: - 主题和样式相关扩展
extension UIView {
    /// 应用圆形样式
    /// - Note: 会根据视图的最小边长设置圆角
    /// - Example:
    ///   ```
    ///   avatarImageView.makeCircular()
    ///   ```
    func makeCircular() {
        layer.cornerRadius = min(width, height) / 2
        clipsToBounds = true
    }

    /// 应用卡片样式
    /// - Parameters:
    ///   - cornerRadius: 圆角半径
    ///   - shadowOpacity: 阴影透明度
    ///   - shadowOffset: 阴影偏移
    ///   - shadowRadius: 阴影半径
    /// - Example:
    ///   ```
    ///   cardView.applyCardStyle(cornerRadius: 12, shadowOpacity: 0.1)
    ///   ```
    func applyCardStyle(cornerRadius: CGFloat = 8,
                   shadowOpacity: Float = 0.1,
                   shadowOffset: CGSize = CGSize(width: 0, height: 2),
                   shadowRadius: CGFloat = 4) {
        backgroundColor = backgroundColor ?? .white
        layer.cornerRadius = cornerRadius
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOpacity = shadowOpacity
        layer.shadowOffset = shadowOffset
        layer.shadowRadius = shadowRadius
        layer.masksToBounds = false
    }

    /// 应用按钮样式
    /// - Parameters:
    ///   - cornerRadius: 圆角半径
    ///   - borderWidth: 边框宽度
    ///   - borderColor: 边框颜色
    /// - Example:
    ///   ```
    ///   buttonView.applyButtonStyle(cornerRadius: 8, borderWidth: 1, borderColor: .blue)
    ///   ```
    func applyButtonStyle(cornerRadius: CGFloat = 8,
                     borderWidth: CGFloat = 1,
                     borderColor: UIColor = .systemBlue) {
        layer.cornerRadius = cornerRadius
        layer.borderWidth = borderWidth
        layer.borderColor = borderColor.cgColor
        clipsToBounds = true
    }
}

14、调试相关

swift 复制代码
// MARK: - 调试相关
extension UIView {
    /// 为视图添加调试边框
    /// - Parameters:
    ///   - color: 边框颜色
    ///   - width: 边框宽度
    /// - Example:
    ///   ```
    ///   #if DEBUG
    ///   view.addDebugBorder(color: .red, width: 1)
    ///   #endif
    ///   ```
    func addDebugBorder(color: UIColor = .red, width: CGFloat = 1) {
        #if DEBUG
                layer.borderColor = color.cgColor
                layer.borderWidth = width
        #endif
    }
    
    /// 打印视图层次结构
    /// - Parameter level: 层级缩进
    /// - Example:
    ///   ```
    ///   #if DEBUG
    ///   view.printHierarchy()
    ///   #endif
    ///   ```
    func printHierarchy(level: Int = 0) {
        #if DEBUG
                let indent = String(repeating: "  ", count: level)
                print("\(indent)\(type(of: self)) - frame: \(frame)")
                
                for subview in subviews {
                    subview.printHierarchy(level: level + 1)
                }
        #endif
    }
    
    /// 为视图添加标识标签(调试用)
    /// - Parameter text: 标签文本
    /// - Example:
    ///   ```
    ///   #if DEBUG
    ///   view.addDebugLabel("MainView")
    ///   #endif
    ///   ```
    func addDebugLabel(_ text: String) {
        #if DEBUG
            let label = UILabel()
            label.text = text
            label.font = UIFont.systemFont(ofSize: 10)
            label.textColor = .red
            label.backgroundColor = UIColor.white.withAlphaComponent(0.8)
            label.sizeToFit()
            label.frame.origin = CGPoint(x: 2, y: 2)
            addSubview(label)
        #endif
    }
}

15、链式编程支持

swift 复制代码
// MARK: - 链式编程支持
extension UIView {
    
    /// 设置背景色(链式调用)
    /// - Parameter color: 背景色
    /// - Returns: 自身实例,支持链式调用
    /// - Example:
    ///   ```
    ///   let view = UIView()
    ///       .backgroundColor(.red)
    ///       .cornerRadius(8)
    ///       .border(width: 1, color: .black)
    ///   ```
    @discardableResult
    func backgroundColor(_ color: UIColor) -> Self {
        backgroundColor = color
        return self
    }
    
    /// 设置透明度(链式调用)
    /// - Parameter alpha: 透明度
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func alpha(_ alpha: CGFloat) -> Self {
        self.alpha = alpha
        return self
    }
    
    /// 设置圆角(链式调用)
    /// - Parameter radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func cornerRadius(_ radius: CGFloat) -> Self {
        layer.cornerRadius = radius
        clipsToBounds = true
        return self
    }
    
    /// 设置边框(链式调用)
    /// - Parameters:
    ///   - width: 边框宽度
    ///   - color: 边框颜色
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func border(width: CGFloat, color: UIColor) -> Self {
        layer.borderWidth = width
        layer.borderColor = color.cgColor
        return self
    }
    
    /// 设置阴影(链式调用)
    /// - Parameters:
    ///   - color: 阴影颜色
    ///   - opacity: 阴影透明度
    ///   - offset: 阴影偏移
    ///   - radius: 阴影半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func shadow(color: UIColor = .black,
                opacity: Float = 0.3,
                offset: CGSize = CGSize(width: 0, height: 2),
                radius: CGFloat = 4) -> Self {
        layer.shadowColor = color.cgColor
        layer.shadowOpacity = opacity
        layer.shadowOffset = offset
        layer.shadowRadius = radius
        layer.masksToBounds = false
        return self
    }
    
    /// 设置用户交互(链式调用)
    /// - Parameter enabled: 是否启用用户交互
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func userInteraction(_ enabled: Bool) -> Self {
        isUserInteractionEnabled = enabled
        return self
    }
    
    /// 设置标签(链式调用)
    /// - Parameter tag: 标签值
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func tag(_ tag: Int) -> Self {
        self.tag = tag
        return self
    }
    
    /// 设置指定角圆角(链式调用)
    /// - Parameters:
    ///   - corners: 要设置圆角的角
    ///   - radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    /// - Example:
    ///   ```
    ///   let cardView = UIView()
    ///       .backgroundColor(.white)
    ///       .roundCorners([.topLeft, .topRight], radius: 16)
    ///       .shadow(color: .black, opacity: 0.1)
    ///   ```
    @discardableResult
    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) -> Self {
        setRoundCorners(corners, radius: radius)
        return self
    }
    
    /// 设置顶部圆角(链式调用)
    /// - Parameter radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func roundTopCorners(radius: CGFloat) -> Self {
        setRoundTopCorners(radius: radius)
        return self
    }
    
    /// 设置底部圆角(链式调用)
    /// - Parameter radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func roundBottomCorners(radius: CGFloat) -> Self {
        setRoundBottomCorners(radius: radius)
        return self
    }
    
    /// 设置左侧圆角(链式调用)
    /// - Parameter radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func roundLeftCorners(radius: CGFloat) -> Self {
        setRoundLeftCorners(radius: radius)
        return self
    }
    
    /// 设置右侧圆角(链式调用)
    /// - Parameter radius: 圆角半径
    /// - Returns: 自身实例,支持链式调用
    @discardableResult
    func roundRightCorners(radius: CGFloat) -> Self {
        setRoundRightCorners(radius: radius)
        return self
    }
}

16、高级动画和效果扩展

swift 复制代码
// MARK: - 高级动画和效果扩展
extension UIView {
    // MARK: - 粒子效果类型枚举
    enum ParticleType {
        case confetti
        case snow
        case stars
    }
    /// 创建波纹效果动画
    /// - Parameters:
    ///   - center: 波纹中心点
    ///   - color: 波纹颜色
    ///   - duration: 动画时长
    /// - Example:
    ///   ```
    ///   view.addRippleEffect(center: tapLocation, color: .blue, duration: 0.6)
    ///   ```
    func addRippleEffect(center: CGPoint, color: UIColor = .lightGray, duration: TimeInterval = 0.6) {
        let rippleLayer = CALayer()
        let diameter = max(bounds.width, bounds.height) * 2
        
        rippleLayer.frame = CGRect(x: center.x - diameter/2, y: center.y - diameter/2, width: diameter, height: diameter)
        rippleLayer.cornerRadius = diameter / 2
        rippleLayer.backgroundColor = color.cgColor
        rippleLayer.opacity = 0.3
        
        layer.addSublayer(rippleLayer)
        
        let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
        scaleAnimation.fromValue = 0
        scaleAnimation.toValue = 1
        
        let opacityAnimation = CABasicAnimation(keyPath: "opacity")
        opacityAnimation.fromValue = 0.3
        opacityAnimation.toValue = 0
        
        let groupAnimation = CAAnimationGroup()
        groupAnimation.animations = [scaleAnimation, opacityAnimation]
        groupAnimation.duration = duration
        groupAnimation.timingFunction = CAMediaTimingFunction(name: .easeOut)
        
        CATransaction.begin()
        CATransaction.setCompletionBlock {
            rippleLayer.removeFromSuperlayer()
        }
        rippleLayer.add(groupAnimation, forKey: "ripple")
        CATransaction.commit()
    }
    
    /// 添加粒子效果
    /// - Parameters:
    ///   - type: 粒子类型
    ///   - colors: 粒子颜色数组
    ///   - duration: 效果持续时间
    /// - Example:
    ///   ```
    ///   view.addParticleEffect(type: .confetti, colors: [.red, .blue, .yellow], duration: 3.0)
    ///   ```
    func addParticleEffect(type: ParticleType, colors: [UIColor], duration: TimeInterval = 2.0) {
        let emitterLayer = CAEmitterLayer()
        emitterLayer.emitterPosition = CGPoint(x: bounds.midX, y: bounds.minY)
        emitterLayer.emitterShape = .line
        emitterLayer.emitterSize = CGSize(width: bounds.width, height: 1)
        
        var emitterCells: [CAEmitterCell] = []
        
        for color in colors {
            let cell = CAEmitterCell()
            cell.birthRate = 10
            cell.lifetime = Float(duration)
            cell.velocity = 100
            cell.velocityRange = 50
            cell.emissionRange = .pi / 4
            cell.scale = 0.3
            cell.scaleRange = 0.2
            cell.color = color.cgColor
            
            switch type {
            case .confetti:
                cell.contents = createConfettiImage().cgImage
                cell.spin = .pi
                cell.spinRange = .pi
            case .snow:
                cell.contents = createSnowflakeImage().cgImage
                cell.yAcceleration = 50
            case .stars:
                cell.contents = createStarImage().cgImage
                cell.spin = .pi / 2
            }
            
            emitterCells.append(cell)
        }
        
        emitterLayer.emitterCells = emitterCells
        layer.addSublayer(emitterLayer)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
            emitterLayer.removeFromSuperlayer()
        }
    }
    
    /// 添加发光效果
    /// - Parameters:
    ///   - color: 发光颜色
    ///   - radius: 发光半径
    ///   - opacity: 发光透明度
    /// - Example:
    ///   ```
    ///   button.addGlowEffect(color: .blue, radius: 10, opacity: 0.8)
    ///   ```
    func addGlowEffect(color: UIColor, radius: CGFloat = 10, opacity: Float = 0.8) {
        layer.shadowColor = color.cgColor
        layer.shadowOffset = .zero
        layer.shadowRadius = radius
        layer.shadowOpacity = opacity
        layer.masksToBounds = false
        
        // 添加动态发光动画
        let pulseAnimation = CABasicAnimation(keyPath: "shadowOpacity")
        pulseAnimation.fromValue = opacity * 0.3
        pulseAnimation.toValue = opacity
        pulseAnimation.duration = 1.0
        pulseAnimation.repeatCount = .infinity
        pulseAnimation.autoreverses = true
        pulseAnimation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
        
        layer.add(pulseAnimation, forKey: "glowPulse")
    }
    
    /// 移除发光效果
    /// - Example:
    ///   ```
    ///   button.removeGlowEffect()
    ///   ```
    func removeGlowEffect() {
        layer.removeAnimation(forKey: "glowPulse")
        layer.shadowOpacity = 0
        layer.shadowRadius = 0
    }
    
    // MARK: - 私有辅助方法
    
    private func createConfettiImage() -> UIImage {
        let size = CGSize(width: 10, height: 10)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        defer { UIGraphicsEndImageContext() }
        
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(UIColor.red.cgColor)
        context.fillEllipse(in: CGRect(origin: .zero, size: size))
        
        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
    }
    
    private func createSnowflakeImage() -> UIImage {
        let size = CGSize(width: 8, height: 8)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        defer { UIGraphicsEndImageContext() }
        
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(UIColor.white.cgColor)
        context.fillEllipse(in: CGRect(origin: .zero, size: size))
        
        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
    }
    
    private func createStarImage() -> UIImage {
        let size = CGSize(width: 12, height: 12)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        defer { UIGraphicsEndImageContext() }
        
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(UIColor.yellow.cgColor)
        
        // 绘制星形
        let center = CGPoint(x: size.width/2, y: size.height/2)
        let radius: CGFloat = 5
        
        context.move(to: CGPoint(x: center.x, y: center.y - radius))
        // 简化的星形绘制
        context.addLine(to: CGPoint(x: center.x + radius, y: center.y + radius))
        context.addLine(to: CGPoint(x: center.x - radius, y: center.y + radius/3))
        context.addLine(to: CGPoint(x: center.x + radius, y: center.y + radius/3))
        context.addLine(to: CGPoint(x: center.x - radius, y: center.y + radius))
        context.closePath()
        context.fillPath()
        
        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
    }
}

17、布局相关高级扩展

swift 复制代码
// MARK: - 布局相关高级扩展
extension UIView {
    
    /// 创建视图的快照视图
    /// - Returns: 快照视图
    /// - Example:
    ///   ```
    ///   let snapshot = originalView.createSnapshot()
    ///   containerView.addSubview(snapshot)
    ///   ```
    func createSnapshot() -> UIView {
        let snapshotView = UIView(frame: frame)
        snapshotView.backgroundColor = backgroundColor
        snapshotView.layer.contents = takeScreenshot()?.cgImage
        return snapshotView
    }
    
    /// 均匀分布子视图(水平)
    /// - Parameters:
    ///   - subviews: 要分布的子视图数组
    ///   - margin: 左右边距
    ///   - spacing: 视图间距
    /// - Example:
    ///   ```
    ///   containerView.distributeSubviewsHorizontally(subviews: [view1, view2, view3], margin: 20, spacing: 10)
    ///   ```
    func distributeSubviewsHorizontally(_ subviews: [UIView], margin: CGFloat = 0, spacing: CGFloat = 0) {
        guard !subviews.isEmpty else { return }
        
        let totalSpacing = spacing * CGFloat(subviews.count - 1)
        let totalMargin = margin * 2
        let availableWidth = width - totalSpacing - totalMargin
        let viewWidth = availableWidth / CGFloat(subviews.count)
        
        for (index, subview) in subviews.enumerated() {
            let x = margin + (viewWidth + spacing) * CGFloat(index)
            subview.frame = CGRect(x: x, y: subview.y, width: viewWidth, height: subview.height)
            
            if subview.superview != self {
                addSubview(subview)
            }
        }
    }
    
    /// 均匀分布子视图(垂直)
    /// - Parameters:
    ///   - subviews: 要分布的子视图数组
    ///   - margin: 上下边距
    ///   - spacing: 视图间距
    /// - Example:
    ///   ```
    ///   containerView.distributeSubviewsVertically(subviews: [view1, view2, view3], margin: 20, spacing: 10)
    ///   ```
    func distributeSubviewsVertically(_ subviews: [UIView], margin: CGFloat = 0, spacing: CGFloat = 0) {
        guard !subviews.isEmpty else { return }
        
        let totalSpacing = spacing * CGFloat(subviews.count - 1)
        let totalMargin = margin * 2
        let availableHeight = height - totalSpacing - totalMargin
        let viewHeight = availableHeight / CGFloat(subviews.count)
        
        for (index, subview) in subviews.enumerated() {
            let y = margin + (viewHeight + spacing) * CGFloat(index)
            subview.frame = CGRect(x: subview.x, y: y, width: subview.width, height: viewHeight)
            
            if subview.superview != self {
                addSubview(subview)
            }
        }
    }
    
    /// 网格布局子视图
    /// - Parameters:
    ///   - subviews: 要布局的子视图数组
    ///   - columns: 列数
    ///   - spacing: 间距
    ///   - margin: 边距
    /// - Example:
    ///   ```
    ///   containerView.layoutSubviewsInGrid(subviews: imageViews, columns: 3, spacing: 10, margin: 20)
    ///   ```
    func layoutSubviewsInGrid(_ subviews: [UIView], columns: Int, spacing: CGFloat = 0, margin: CGFloat = 0) {
        guard !subviews.isEmpty && columns > 0 else { return }
        
        let rows = Int(ceil(Double(subviews.count) / Double(columns)))
        let availableWidth = width - margin * 2 - spacing * CGFloat(columns - 1)
        let availableHeight = height - margin * 2 - spacing * CGFloat(rows - 1)
        let itemWidth = availableWidth / CGFloat(columns)
        let itemHeight = availableHeight / CGFloat(rows)
        
        for (index, subview) in subviews.enumerated() {
            let row = index / columns
            let column = index % columns
            
            let x = margin + (itemWidth + spacing) * CGFloat(column)
            let y = margin + (itemHeight + spacing) * CGFloat(row)
            
            subview.frame = CGRect(x: x, y: y, width: itemWidth, height: itemHeight)
            
            if subview.superview != self {
                addSubview(subview)
            }
        }
    }
}

18、性能优化相关扩展

swift 复制代码
// MARK: - 性能优化相关扩展
extension UIView {
    
    /// 启用/禁用光栅化以优化性能
    /// - Parameter enabled: 是否启用光栅化
    /// - Example:
    ///   ```
    ///   complexView.setRasterization(enabled: true) // 提升滚动性能
    ///   ```
    func setRasterization(enabled: Bool) {
        layer.shouldRasterize = enabled
        layer.rasterizationScale = enabled ? UIScreen.main.scale : 1.0
    }
    
    /// 预加载视图(触发布局和渲染)
    /// - Example:
    ///   ```
    ///   heavyView.preload() // 在后台预加载复杂视图
    ///   ```
    func preload() {
        _ = layer.presentation()
        layoutIfNeeded()
    }
    
    /// 异步更新UI
    /// - Parameter updates: 更新操作
    /// - Example:
    ///   ```
    ///   view.asyncUpdateUI {
    ///       // 执行UI更新
    ///       self.backgroundColor = .red
    ///   }
    ///   ```
    func asyncUpdateUI(_ updates: @escaping () -> Void) {
        DispatchQueue.main.async {
            updates()
        }
    }
}
相关推荐
低代码布道师6 小时前
Next.js 16 全栈实战(一):从零打造“教培管家”系统——环境与脚手架搭建
开发语言·javascript·ecmascript
符哥20086 小时前
用Apollo + RxSwift + RxCocoa搭建一套网络请求框架
网络·ios·rxswift
念何架构之路6 小时前
Go进阶之panic
开发语言·后端·golang
亓才孓6 小时前
[Properties]写配置文件前,必须初始化Properties(引用变量没执行有效对象,调用方法会报空指针错误)
开发语言·python
傻乐u兔6 小时前
C语言进阶————指针3
c语言·开发语言
两点王爷6 小时前
Java基础面试题——【Java语言特性】
java·开发语言
Swift社区6 小时前
Gunicorn 与 Uvicorn 部署 Python 后端详解
开发语言·python·gunicorn
码农阿豪7 小时前
Python Flask应用中文件处理与异常处理的实践指南
开发语言·python·flask
岁岁种桃花儿7 小时前
CentOS7 彻底卸载所有JDK/JRE + 重新安装JDK8(实操完整版,解决kafka/jps报错)
java·开发语言·kafka