Ios 来自调试器的消息:由于内存问题而终止
我的应用程序正在使用Ios 来自调试器的消息:由于内存问题而终止,ios,swift,mapbox,mapbox-gl,mapbox-marker,Ios,Swift,Mapbox,Mapbox Gl,Mapbox Marker,我的应用程序正在使用Geojson文件。我用于将MGLPolyline添加到地图。但问题是我的文件太大,因此应用程序崩溃并从调试器获得错误:消息:由于内存问题而终止。在第一个循环中,我遇到了66234个对象。我尝试将数组分块到新数组,但没有成功。请帮我解决这个问题。这是我在地图上绘制的代码,这是我的,如果有任何不同的第三方可以解决我的问题,也欢迎使用: func drawPolyline() { // Parsing GeoJSON can be CPU intensive, do i
Geojson
文件。我用于将MGLPolyline
添加到地图。但问题是我的文件太大,因此应用程序崩溃并从调试器获得错误:消息:由于内存问题而终止
。在第一个循环中,我遇到了66234个对象。我尝试将数组分块到新数组,但没有成功。请帮我解决这个问题。这是我在地图上绘制的代码,这是我的,如果有任何不同的第三方可以解决我的问题,也欢迎使用:
func drawPolyline() {
// Parsing GeoJSON can be CPU intensive, do it on a background thread
DispatchQueue.global(qos: .background).async {
// Get the path for example.geojson in the app's bundle
let jsonPath = Bundle.main.path(forResource: "KMLMAPNew", ofType: "json")
let jsonData = NSData(contentsOfFile: jsonPath!)
do {
// Load and serialize the GeoJSON into a dictionary filled with properly-typed objects
guard let jsonDict = try JSONSerialization.jsonObject(with: jsonData! as Data, options: []) as? Dictionary<String, AnyObject>, let features = jsonDict["features"] as? Array<AnyObject> else{return}
for feature in features {
guard let feature = feature as? Dictionary<String, AnyObject>, let geometry = feature["geometry"] as? Dictionary<String, AnyObject> else{ continue }
if geometry["type"] as? String == "LineString" {
// Create an array to hold the formatted coordinates for our line
var coordinates: [CLLocationCoordinate2D] = []
if let locations = geometry["coordinates"] as? Array<AnyObject> {
// Iterate over line coordinates, stored in GeoJSON as many lng, lat arrays
for location in locations {
// Make a CLLocationCoordinate2D with the lat, lng
if let location = location as? Array<AnyObject>{
let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)
// Add coordinate to coordinates array
coordinates.append(coordinate)
}
}
}
let line = MGLPolyline(coordinates: &coordinates, count: UInt(coordinates.count))
// Optionally set the title of the polyline, which can be used for:
// - Callout view
// - Object identification
line.title = "Crema to Council Crest"
// Add the annotation on the main thread
DispatchQueue.main.async {
// Unowned reference to self to prevent retain cycle
[unowned self] in
self.mapboxView.addAnnotation(line)
}
}
}
}
catch
{
print("GeoJSON parsing failed")
}
}
}
func drawPolyline(){
//解析GeoJSON可能是CPU密集型的,在后台线程上进行
DispatchQueue.global(qos:.background).async{
//获取应用程序包中example.geojson的路径
让jsonPath=Bundle.main.path(forResource:“KMLMAPNew”,类型为:“json”)
让jsonData=NSData(contentsOfFile:jsonPath!)
做{
//将GeoJSON加载并序列化到充满正确类型对象的字典中
guard let jsonDict=try JSONSerialization.jsonObject(使用:jsonData!作为数据,选项:[])作为字典,让features=jsonDict[“features”]作为数组else{return}
对于要素中的要素{
guard let feature=feature as?Dictionary,let geometry=feature[“geometry”]as?Dictionary else{continue}
如果几何体[“键入”]为?字符串==“LineString”{
//创建一个数组来保存线的格式化坐标
变量坐标:[CLLocationCoordinate2D]=[]
如果让位置=几何体[“坐标”]作为数组{
//迭代线坐标,存储在GeoJSON中,尽可能多的lng、lat数组
对于位置中的位置{
//与lat、lng协调定位
如果let location=location as?数组{
让坐标=CLLocationCoordinate2DMake(位置[1]。双值,位置[0]。双值)
//将坐标添加到坐标数组
坐标。追加(坐标)
}
}
}
let line=MGLPolyline(坐标:&coordinates,计数:UInt(coordinates.count))
//(可选)设置多段线的标题,该标题可用于:
//-详图索引视图
//-物体识别
line.title=“Crema至议会徽章”
//在主线程上添加注释
DispatchQueue.main.async{
//无主引用到self以防止保留循环
[无主的自己]在
self.mapboxView.addAnnotation(行)
}
}
}
}
抓住
{
打印(“GeoJSON解析失败”)
}
}
}
编辑::@Alessandro Ornano和@fragilecat非常感谢。但这些解决方案仍然无法解决iPad上应用程序的终止问题。我认为更改当前代码以使其正常工作非常困难,因为数据太大了。我想我需要另一个与大数据相关的解决方案。比如将数组分块到小数组中,然后按队列加载它们。但我不知道如何开始:(
我向MapBox的支持团队发送了一封电子邮件,征求建议。第一个解决方案 可能您的for循环无限运行,每次都将内存分配给一个具有nil值的数组。它使用了大量内存,因此会产生此错误 请在for循环中打印一些内容进行检查 第二种解决方案 将此添加到didReceiveMemoryWarning中:
NSURLCache.sharedURLCache().removeAllCachedResponses()
NSURLCache.sharedURLCache().diskCapacity = 0
NSURLCache.sharedURLCache().memoryCapacity = 0
您还可以更改NSURLRequest
的缓存策略:
let day_url = NSURL(string: "http://www.example.com")
let day_url_request = NSURLRequest(URL: day_url,
cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 10.0)
let day_webView = UIWebView()
day_webView.loadRequest(day_url_request)
有关缓存策略的更多信息。这里的问题与有效的内存管理有关。您正在通过json文件加载大量数据。您意识到您需要在后台队列(线程)上完成大部分工作但是,问题是如何在当前版本的
drawPolyline()中通过DispatchQueue.main.async
函数更新UI
method根据第一个循环中对象的数量,您在后台队列和主队列之间切换66234次。此外,您还创建了相同数量的CLLocationCoordinate2D
数组
这会导致巨大的内存占用。您没有提到有关如何渲染线条的任何要求。因此,如果我们重新构造drawPolyline()
方法为CLLocationCoordinate2D
数组使用一个实例变量,因此我们只使用一个实例变量,然后在更新UI之前处理所有json文件。内存使用量下降到更易于管理的664.6 MB
当然,渲染可能不是您想要的,如果是这种情况,您可能希望将CLLocationCoordinate2D
数组重新构造为更合适的数据结构
下面是您的ViewController
类,它将drawPolyline()重写为drawPolyline2()
导入UIKit
导入映射框
类ViewController:UIViewController、MGLMapViewDelegate{
@IBMOutlet var mapboxView:MGLMapView!
fileprivate变量坐标=[[CLLocationCoordinate2D]]()
fileprivate var jsonData:NSData?
重写func viewDidLoad(){
super.viewDidLoad()
//加载视图后,通常从nib执行任何其他设置。
mapboxView=MGLMapView(帧:view.bounds)
mapboxView.autoresizingMask=[.flexibleWidth、.flexibleHeight]
//mapboxView.setCenter(CLLocationCoordinate2D)(纬度:45.507
import UIKit
import Mapbox
class ViewController: UIViewController, MGLMapViewDelegate {
@IBOutlet var mapboxView: MGLMapView!
fileprivate var coordinates = [[CLLocationCoordinate2D]]()
fileprivate var jsonData: NSData?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
mapboxView = MGLMapView(frame: view.bounds)
mapboxView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// mapboxView.setCenter(CLLocationCoordinate2D(latitude: 45.5076, longitude: -122.6736),
// zoomLevel: 11, animated: false)
mapboxView.setCenter(CLLocationCoordinate2D(latitude: 1.290270, longitude: 103.851959),
zoomLevel: 11, animated: false)
view.addSubview(self.mapboxView)
mapboxView.delegate = self
mapboxView.allowsZooming = true
drawPolyline2()
//newWay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func drawPolyline2() {
DispatchQueue.global(qos: .background).async {
if let path = Bundle.main.path(forResource: "KMLMAPNew", ofType: "json") {
let fileURL = URL(fileURLWithPath: path)
if let data = try? Data(contentsOf: fileURL) {
do {
let dictionary = try JSONSerialization.jsonObject(with: data as Data, options: []) as? Dictionary<String, AnyObject>
if let features = dictionary?["features"] as? Array<AnyObject> {
print("** START **")
for feature in features {
guard let feature = feature as? Dictionary<String, AnyObject>, let geometry = feature["geometry"] as? Dictionary<String, AnyObject> else { continue }
if geometry["type"] as? String == "LineString" {
// Create an array to hold the formatted coordinates for our line
if let locations = geometry["coordinates"] as? Array<AnyObject> {
// Iterate over line coordinates, stored in GeoJSON as many lng, lat arrays
var featureCoordinates = [CLLocationCoordinate2D]()
for location in locations {
// Make a CLLocationCoordinate2D with the lat, lng
if let location = location as? Array<AnyObject>{
let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)
// Add coordinate to coordinates array
featureCoordinates.append(coordinate)
}
}
// Uncomment if you need to store for later use.
//self.coordinates.append(featureCoordinates)
DispatchQueue.main.async {
let line = MGLPolyline(coordinates: &featureCoordinates, count: UInt(featureCoordinates.count))
// Optionally set the title of the polyline, which can be used for:
// - Callout view
// - Object identification
line.title = "Crema to Council Crest"
self.mapboxView.addAnnotation(line)
}
}
}
}
print("** FINISH **")
}
} catch {
print("GeoJSON parsing failed")
}
}
}
}
}
func drawSmallListObj(list: [Dictionary<String, AnyObject>]){
for obj in list{
// print(obj)
if let feature = obj as? Dictionary<String, AnyObject> {
if let geometry = feature["geometry"] as? Dictionary<String, AnyObject> {
if geometry["type"] as? String == "LineString" {
// Create an array to hold the formatted coordinates for our line
var coordinates: [CLLocationCoordinate2D] = []
if let locations = geometry["coordinates"] as? Array<AnyObject> {
// Iterate over line coordinates, stored in GeoJSON as many lng, lat arrays
for location in locations {
// Make a CLLocationCoordinate2D with the lat, lng
if let location = location as? Array<AnyObject>{
let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)
// Add coordinate to coordinates array
coordinates.append(coordinate)
}
}
}
let line = MGLPolyline(coordinates: &coordinates, count: UInt(coordinates.count))
// Optionally set the title of the polyline, which can be used for:
// - Callout view
// - Object identification
line.title = "Crema to Council Crest"
// Add the annotation on the main thread
DispatchQueue.main.async {
// Unowned reference to self to prevent retain cycle
[unowned self] in
self.mapboxView.addAnnotation(line)
}
}
}
}
}
}
func mapView(_ mapView: MGLMapView, alphaForShapeAnnotation annotation: MGLShape) -> CGFloat {
// Set the alpha for all shape annotations to 1 (full opacity)
return 1
}
func mapView(_ mapView: MGLMapView, lineWidthForPolylineAnnotation annotation: MGLPolyline) -> CGFloat {
// Set the line width for polyline annotations
return 2.0
}
func mapView(_ mapView: MGLMapView, strokeColorForShapeAnnotation annotation: MGLShape) -> UIColor {
// Give our polyline a unique color by checking for its `title` property
if (annotation.title == "Crema to Council Crest" && annotation is MGLPolyline) {
// Mapbox cyan
return UIColor(red: 59/255, green:178/255, blue:208/255, alpha:1)
}
else
{
return UIColor.red
}
}
}
DispatchQueue.main.async {
// weaked reference to self to prevent retain cycle
[weak self] in
guard let strongSelf = self else { return }
strongSelf.mapboxView.addAnnotation(line)
}
func drawPolyline() {
DispatchQueue.global(qos: .background).async {
[weak self] in
guard let strongSelf = self else { return }
let jsonPath = Bundle.main.path(forResource: "KMLMAPNew", ofType: "json")
let jsonData = NSData(contentsOfFile: jsonPath!)
do {
guard let jsonDict = try JSONSerialization.jsonObject(with: jsonData! as Data, options: []) as? Dictionary<String, AnyObject>, let features = jsonDict["features"] as? Array<AnyObject> else{return}
for feature in features {
guard let feature = feature as? Dictionary<String, AnyObject>, let geometry = feature["geometry"] as? Dictionary<String, AnyObject> else{ continue }
if geometry["type"] as? String == "LineString" {
var coordinates: [CLLocationCoordinate2D] = []
if let locations = geometry["coordinates"] as? Array<AnyObject> {
for location in locations {
if let location = location as? Array<AnyObject>{
let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)
coordinates.append(coordinate)
}
}
}
let line = MGLPolyline(coordinates: &coordinates, count: UInt(coordinates.count))
line.title = "Crema to Council Crest"
print(feature) // Added this line just for debug to see the flow..
DispatchQueue.main.async {
strongSelf.mapboxView.addAnnotation(line)
}
}
}
}
catch
{
print("GeoJSON parsing failed")
}
}
}
func newWay(){
DispatchQueue.global(qos: .background).async {
[weak self] in
guard let strongSelf = self else { return }
let jsonPath = Bundle.main.path(forResource: "KMLMAPNew", ofType: "json")
let jsonData = NSData(contentsOfFile: jsonPath!)
do {
if let jsonDict = try JSONSerialization.jsonObject(with: jsonData! as Data, options: []) as? Dictionary<String, AnyObject> {
if let features = jsonDict["features"] as? Array<AnyObject> {
let chunks = stride(from: 0, to: features.count, by: 2).map {
Array(features[$0..<min($0 + 2, features.count)])
}
for obj in chunks{
strongSelf.drawSmallListObj(list: obj as! [Dictionary<String, AnyObject>])
}
}
}
}
catch
{
print("GeoJSON parsing failed")
}
}
}
func drawSmallListObj(list: [Dictionary<String, AnyObject>]){
for obj in list{
if let feature = obj as? Dictionary<String, AnyObject> {
if let geometry = feature["geometry"] as? Dictionary<String, AnyObject> {
if geometry["type"] as? String == "LineString" {
var coordinates: [CLLocationCoordinate2D] = []
if let locations = geometry["coordinates"] as? Array<AnyObject> {
for location in locations {
if let location = location as? Array<AnyObject>{
let coordinate = CLLocationCoordinate2DMake(location[1].doubleValue, location[0].doubleValue)
coordinates.append(coordinate)
}
}
}
let line = MGLPolyline(coordinates: &coordinates, count: UInt(coordinates.count))
line.title = "Crema to Council Crest"
DispatchQueue.main.async {
[weak self] in
guard let strongSelf = self else { return }
strongSelf.mapboxView.addAnnotation(line)
}
}
}
}
}
}
func loopALot() {
for _ in 0 ..< 5000 {
let image = NSImage(contentsOfFile: filename)
}
}
func loopALot() {
for _ in 0 ..< 5000 {
autoreleasepool {
let image = NSImage(contentsOfFile: filename)
}
}
}