在矩形请求上设置属性。 iOS,Swift

时间:2018-08-13 15:13:15

标签: ios swift

我正在尝试在矩形请求上设置属性。 我试图设置最小尺寸,宽高比和其他尺寸,但出现以下错误。

  

致命错误:尝试读取一个未拥有的引用但对象已被释放2018-08-13 16:08:09.081049 + 0100 app [4000:1277980]致命错误:尝试读取一个未拥有的引用但对象已被释放

func performVisionRequest(image: CGImage, orientation: CGImagePropertyOrientation) {

    DispatchQueue.global(qos: .userInitiated).async {
        do {
            let imageRequestHandler = VNImageRequestHandler(cgImage: image, orientation: orientation, options: [:])
            try imageRequestHandler.perform(
                [VNDetectRectanglesRequest(completionHandler:{ req, err in
                    self.rectanglesRequest(request:req, error:err)

                })]
            )
        } catch let error as NSError {
            self.sliceCompletion([UIImage]())
            print("Failed to perform vision request: \(error)")

        }
    }
}

func rectanglesRequest(request: VNRequest, error: Error?) {
    if let err = error as NSError? {
        noRect = true
        var slices = [imageNo]
        self.sliceCompletion(slices as! [UIImage])
        slices = []
        print("Failed during detection: \(err.localizedDescription)")
        return
    }
    unowned let rectanglesRequestSet = VNDetectRectanglesRequest()

    rectanglesRequestSet.minimumSize = 0.07
    rectanglesRequestSet.minimumAspectRatio = 0.2
    rectanglesRequestSet.maximumAspectRatio = 0.3
    rectanglesRequestSet.quadratureTolerance = 22.0

1 个答案:

答案 0 :(得分:2)

此处将rectanglesRequestSet标记为unowned并不好,因为它会导致它在使用前以及尝试向已释放的unowned对象发送消息时被释放。将会崩溃,这说明了您收到的消息:

  

试图读取一个未拥有的引用,但该对象已经被释放

unowned用于打破保留周期,这种保留周期是在类的属性通常通过闭包将引用保留给类本身时发生的。例如:

class ViewControllerA: UIViewController {
    let viewControllerB = UIViewControllerB()

    override func viewDidLoad() {
        super.viewDidLoad()
        viewControllerB.onSelect = {
            self.onSelection() 
        }
    }

    func onSelection() {
        // do something
    }
}

class ViewControllerB: UIViewController {
    var onSelect: (() -> Void)?
}

例如,上面的代码创建了一个vcA-> vcB-> onSelect-> vcA的保留周期,其中vcAViewControllerAvcBViewControllerB的实例。 vcAvcB永远不会被释放,因为vcA拥有对vcB的引用,因为它是一个属性。并且,vcB通过vcA闭包中的变量捕获来持有对onSelect的引用。发生这种情况的原因是,为了使闭包将来能够执行代码,它们必须持有对闭包中使用的所有对象的引用,在示例vcA是唯一使用的对象,因此闭包保留对其的引用,并且vcB引用了闭包。为防止此保留周期:

viewControllerB.onSelect = { [unowned self]
    self.onSelection() 
}

viewControllerB.onSelect = { [weak self]
    self?.onSelection() 
}

将导致闭包不捕获vcA,这意味着将没有保留周期。使用weak比使用unowned更安全。闭包不能保证未捕获的对象将在执行时出现weak,将允许这样的对象成为nilunowned在某种程度上规定它将不会nil,并指示程序崩溃。