我正在编写一个使用反转地理编码和CLGeocoder命令的应用程序,我正在使用Xcode 11.3和Swift 5。我使用的是Xcode 11.3和Swift 5。
我使用的代码是标准的,并且可以工作,即我可以很好地执行反向地理编码。 问题是,我的应用程序每隔5分钟就会调用反向地理编码来报告当前的地址--这个工作绝对正常......然而,大约4天后,我的应用程序在我的测试iPhone上不再工作了。 当我说不再工作,我的意思是,我点击图标打开应用程序,它返回到IOS。 当我在模拟器上运行应用程序时,我可以看到大约每5分钟内存消耗就会增加0.01MB,这表明也许在4天后容器内存已满,应用程序停止正常工作。
因此综上所述,我的问题是有没有人注意到,当使用反向地理编码一段时间后,他们的应用无法正常运行。
我知道它的反向地理编码,因为如果我不调用函数,那么内存消耗就会保持静态。
我知道有限制的频率,你可以调用reversegeolocation - 也许苹果知道它的泄漏,这就是为什么限制在那里(以分散人们从做我正在做的事情)?
我已经附上了整个股票标准代码。 我稍微修改了一下,去掉了频率元素,现在让你点击屏幕上的按钮来触发反向定位......。大约10次点击后,你会看到你的内存增加,如果你继续这样做,你会继续看到内存增加......。(最好每隔15 - 20秒试一次)....
我的代码。
import Foundation
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
let locationManager:CLLocationManager = CLLocationManager()
var currentLatitude: Double = 37.33030778
var currentLongitude: Double = -122.02896839
@IBOutlet var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
locationManager.delegate = self
print("Running")
}
@IBAction func myButtonPressed(_ sender: Any) {
// Print inside IBACTION
print("Inside IBACTION")
// incease latitude and longitue
currentLatitude = currentLatitude + 0.10
currentLongitude = currentLongitude + 0.10
myReverseGeo()
}
func myReverseGeo() {
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
let geocoder: CLGeocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in
if error != nil {
let errorString = String(describing: error?.localizedDescription)
print("Reverse Geocoding failed")
print(errorString)
return
}
let placemark = placemarks! as [CLPlacemark]
if placemark.count > 0 {
let placemark = placemarks![0]
let eventCity = placemark.locality
let eventState = placemark.subAdministrativeArea
let eventCountry = placemark.country
print(eventCity!)
print(eventState!)
print(eventCountry!)
}
})
}
}
我不认为你的内存问题是来自于这个例程。我运行了144次迭代(12分钟,每5秒发射一次;相当于每5分钟运行12小时),没有看到明显的内存增长。
(每一个 "兴趣点 "标志都是一个反向地理编码请求)
不过,有几点观察。
但有几点观察: CLGeocoder
每一个请求,我都会实例化一个,并反复执行 reverseGeocodeLocation
用这一个实例进行调用。
关于对 CLGeocoder
主要的限制是你不能同时执行geocode请求(如果你试图这样做,它只是失败与错误)。
关于你为什么会出现内存增长,我无法评论,因为我无法重现你描述的行为。也许你打开了一些调试选项(malloc堆栈痕迹,僵尸等)。这将产生你所描述的行为。关闭所有可选的内存诊断程序,并执行一次发布构建。
如果内存在增长,有两个工具是有用的。
"Debug Memory Graph "将向你展示已经创建的对象,你可以查看在哪里建立了哪些强引用。
如果你使用Instruments中的 "Leaks "工具(它还提供了 "Allocations "工具)对应用程序进行剖析,你就可以确切地检查哪些分配在哪里被创建了。
如需了解更多信息,请参阅 Leaks仪器不显示内存泄漏,如何调试?
一般情况下,如果我们要寻找用户位置的更新,在 访问服务 和 重变服务 是更高效的方式。为什么要通过每五分钟做一次来消耗用户的电池呢,因为用户会有很长的时间跨度没有移动。让设备在用户移动时告诉你的应用,而不是不断地进行投票。
这不是非常相关的,但这是我生成上面图片的代码。
var counter = 0
var simulatedTimeInterval: TimeInterval = 0
let maxCounter = 12 * 60 / 5 // how many geocode request in 12 hours, every five minutes
let formatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
return formatter
}()
func startTimer() {
Timer.scheduledTimer(withTimeInterval: 5, repeats: true) { [weak self] timer in
guard
let self = self,
self.counter < self.maxCounter
else {
timer.invalidate()
return
}
self.counter += 1
self.simulatedTimeInterval += 60 * 5 // add 5 minutes
let simulatedTimeString = self.formatter.string(from: self.simulatedTimeInterval)!
os_signpost(.event, log: pointsOfInterest, name: "Geocode", "Request #%d @ %{public}@", self.counter, simulatedTimeString)
self.updateLocation()
self.myReverseGeo()
}
print("Running")
}
func updateLocation() {
currentLatitude += 0.010
currentLongitude += 0.010
}
func myReverseGeo() {
let location = CLLocation(latitude: currentLatitude, longitude: currentLongitude)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { placemarks, error in
guard
error == nil,
let placemark = placemarks?.first,
let city = placemark.locality,
let state = placemark.administrativeArea,
let country = placemark.country
else {
print("Reverse Geocoding failed")
print(error ?? "No placemarks found")
return
}
print(city, state, country)
}
}
有了
import os.signpost
let pointsOfInterest = OSLog(subsystem: "Geocode", category: .pointsOfInterest)