Swift递归闭包堆栈溢出错误

时间:2018-01-10 18:27:57

标签: swift recursion closures stack-overflow

更新:应该注意的是,下面的问题是学术性的,核心位置的使用,或者位置数据的轮询与问题无关 - 这样做的正确方法始终是通过核心位置代表方法。我最初的问题最终归结为:“swift中是否有无限递归?(或尾递归)”。答案是否定的。这是由于堆栈空间耗尽导致我的错误的原因。

原始问题: 我遇到了一个通过闭包传递值的递归函数的问题。我是一个长期的Objective-C开发人员,但没有在Swift编程很长时间,所以也许我错过了一些明显的东西。这是函数以及我如何调用它:

public func getLocation(completion: @escaping (CLLocationCoordinate2D?) -> ())
{
    completion(self.currentLocation)
    weak var weakSelf = self
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
        weakSelf?.getLocation(completion: {location in
            completion(weakSelf?.currentLocation)
        })
    }
}

LocationManager.shared.getLocation(completion: {location in
        if(location != nil)
        {
            weakSelf?.lonLabel.text = "Lat: " + location!.latitude.description
            weakSelf?.latLabel.text = "Lon: " + location!.longitude.description
        }
    })

我在运行一段时间后得到的错误(描述Thread 1: EXC_BAD_ACCESS (code=2, address=0x16f1b7fd0))是:

enter image description here

我要完成的是将自动更新位置值传递给位置管理器对象。我想另一种方法是用performSelector withObject afterDelay完成,但此时,我只是想知道为什么会崩溃?

1 个答案:

答案 0 :(得分:5)

通过getLocation(completion:)调用getLocation(completion:)调用getLocation(completion:),直到用完堆栈空间,导致堆栈溢出。

您可以改为使用DispatchSourceTimer

import Dispatch

let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.main)
timer.schedule(deadline: .now(), repeating: .seconds(5), leeway: .milliseconds(100))

timer.setEventHandler { [weak self] in
    guard let strongSelf = self,
          let location = LocationManager.shared.currentLocation else { return }
    strongSelf.lonLabel.text = "Lat: \(location.latitude)"
    strongSelf.latLabel.text = "Lon: \(location.longitude)"
}

timer.resume()

但是这整个民意调查方法都没有任何意义。您的位置代表已被告知位置更改。您可以随后更改标签。