ios - 在大型 UIView 上绘制占用大量内存

标签 ios swift uiview

当我开始在大型 UIView(宽度:3700,高度:40000)上绘制时,它会占用大量内存 当应用程序启动时,内存是 150 MB,当开始在上面绘图时(调用 setNeedsDisplay 方法)大约需要 1 GB,应用程序会崩溃

class DrawingVc: UIViewController {

    let  contentView = DrawableView()
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.backgroundColor = .clear
        self.view.addSubview(contentView)
        contentView.frame = CGRect(x: 0, y: 0, width:view.frame.width,  height: 
        view.frame.height * 50)
 }

这里是自定义view的代码,可以看到,setNeedsDisplay运行在touchMoves

 class DrawableView: UIView {

    var mLastPath: UIBezierPath?
    weak var scdelegate: DrawableViewDelegate?
    var isDrawEnable = true

    private var drawingLines : [UIBezierPath] = []

    override init(frame: CGRect) {
        super.init(frame: frame)

    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

    }


    override func draw(_ rect: CGRect) {
        debugPrint("request draw")

        drawLine()

    }

    private func drawLine() {

        UIColor.blue.setStroke()
        for line in drawingList {
            line.lineWidth = 4
            line.stroke()
            line.lineCapStyle = .round
        }


    }

    var drawingList = [UIBezierPath]()
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if touches.count == 2 {
            return
        }

        let location = (touches.first?.location(in: self))!
        mLastPath = UIBezierPath()
        mLastPath?.move(to: location)
        prevPoint = location

        drawingList.append(mLastPath!)
    }

        var prevPoint: CGPoint?
      var isFirst = true
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        debugPrint("touchesMoved: " , (touches.first?.location(in: self).x)!  , (touches.first?.location(in: self).y)! )
        if let coalescedtouches =  event?.coalescedTouches(for: touches.first!)
        {
            for coalescedTouch in coalescedtouches
            {
                let locationInView = coalescedTouch.location(in: self)

                if let prevPoint = prevPoint {
                    let midPoint = CGPoint( x: (locationInView.x   + prevPoint.x) / 2, y: (locationInView.y + prevPoint.y) / 2)
                    if isFirst {
                        mLastPath?.addLine(to: midPoint)
                    }else {

                        mLastPath?.addQuadCurve(to: midPoint, controlPoint: prevPoint)
                    }
                    isFirst = false
                } else {
                    mLastPath?.move(to: locationInView)

                }
                prevPoint = locationInView
            }

        }
        setNeedsDisplay()
    }



}

是什么导致了这个问题,如何解决?

最佳答案

您的 View 大于 iOS 设备上可能的最大屏幕,所以我想您的 View 嵌入在 ScrollView 中。您应该只绘制 View 的可见部分。不幸的是,UIView 不直接支持这一点。你可以看看CATiledLayer ,它支持仅绘制图层的可见部分,并且它也支持缩放图层的不同级别的细节。

关于ios - 在大型 UIView 上绘制占用大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48366057/

相关文章:

iphone - 释放UIView会自动调用removeFromSuperView吗?

uiview - 与CATiledLayer一起使用时UIView的 "contentScaleFactor"背后的 secret 是什么?

ios - 具有后台模式和来电通知的 SIP 应用程序

android - Phonegap Build ios 6 iphone 5 启动画面不会消失

SwiftUI:如何在 ForEach 循环中放置一个换行符,以重复其中的 View

ios - 如何将 UIView 转换为高分辨率的 UIImage?

iOS NSMutableURLRequest 授权 header

ios - Xcode 6 在使用 Swift 编码进行预测时添加了两个点(句点)

ios - 将新的配置文件添加到现有的 TestFlight 构建

ios - 以编程方式在其他 View 的底部添加 subview