iOS Swift:访问最后一个属性时,数组索引超出范围

时间:2014-11-28 06:23:56

标签: ios arrays swift ios8 xcode6.1

我遇到了一个奇怪的错误。我正在向一个数组附加一个项目,然后通过.last属性访问该项目,但我随机得到一个“致命错误:数组索引超出范围”。

这是我的代码(在for循环中):

var thisLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
currentMarkers.append(GMSMarker(position: thisLocation))

var calle = obj["calle"] as String
var numero = obj["numero"] as String
var colonia = obj["colonia"] as String
var direccion = "\(calle) \(numero), \(colonia)"
var horarioSemanal = obj["horario_lv"] as String
var horarioSabatino = obj["horario_s"] as String
var nombre = obj["sucursal"] as String

currentMarkers.last?.icon = UIImage(named: tipo.lowercaseString)
currentMarkers.last?.title = "\(tipo) - \(nombre)"
currentMarkers.last?.appearAnimation = kGMSMarkerAnimationPop
currentMarkers.last?.snippet = direccion

错误随机显示在最后四行之一中。 我也试过通过以下方式访问它:

currentMarkers[currentMarkers.count-1].snippet = direccion

没有运气。

这段代码是一个名为fetchSucursales()的函数的一部分,我在后台调用它是这样的:

let qualityOfServiceClass = Int(QOS_CLASS_BACKGROUND.value)
let inverseQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(inverseQueue, {

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.labelStatus.text = "Obteniendo marcadores..."
        self.activityIndicatorUpdateMarkers.startAnimating()
    })

    self.fetchSucursales()

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.labelStatus.text = "\(self.currentMarkers.count) marcadores encontrados."
        self.activityIndicatorUpdateMarkers.stopAnimating()
    })

})

如果我在主队列中运行它,每次都能正常运行:

    labelStatus.text = "Obteniendo marcadores..."
    activityIndicatorUpdateMarkers.startAnimating()
    fetchNearbyPlaces()
    labelStatus.text = "\(currentMarkers.count) marcadores encontrados."
    activityIndicatorUpdateMarkers.stopAnimating()

只是我的应用程序在取出标记时会冻结,如果我这样做的话。

它是随机的,在不同的行(以及每次循环次数不同)之后的事实让我觉得它与它在后台运行有关。

我正在使用Xcode 6.1(6A1052d)。

希望你能帮助我,并提前多多谢谢!

修改

实现Nate的答案,现在错误已转移到另一行,这是我的函数的开始:

func fetchSucursales() {

mapView.clear()
currentMarkers.removeAll(keepCapacity: false)
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(NSBundle.mainBundle().bundlePath)!
while let element = enumerator.nextObject() as? String {
    if element.hasSuffix("json") {

        let path = NSBundle.mainBundle().pathForResource(element.stringByDeletingPathExtension, ofType: element.pathExtension)
        let jsonData = NSData(contentsOfFile: path!, options: .DataReadingMappedIfSafe , error: nil)
        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        var sucursales : NSArray = jsonResult["markers"] as NSArray

        sucursalLoop: for sucursal in sucursales {
            let obj = sucursal as NSDictionary

            var tipo = obj["tipo"] as String
            var latitude:CLLocationDegrees = obj["latitud"]!.doubleValue
            var longitude:CLLocationDegrees = obj["longitud"]!.doubleValue
            if contains(searchedTypes, tipo.lowercaseString) {
                //if latitude < mapRadius["norte"] && latitude > mapRadius["sur"] && longitude > mapRadius["este"] && longitude < mapRadius["oeste"] {

                for var index:Int = 0; index < currentMarkers.count; ++index {
                    if latitude == currentMarkers[index].position.latitude && longitude == currentMarkers[index].position.longitude {
                        if tipo.lowercaseString == "cajero" {
                            continue sucursalLoop
                        }else {

                            if currentMarkers[index].title.rangeOfString("cajero") != nil {
                                currentMarkers.removeAtIndex(index)
                            }
                            //append
                        }
                    }
                }

                //Append
                var thisLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
                let newMarker = GMSMarker(position: thisLocation)
                var calle = obj["calle"] as String
                //Rest of code posted before

现在错误显示在if纬度== currentMarkers [index] .position.latitude&amp;&amp; longitude == currentMarkers [index] .position.longitude {line或in if currentMarkers [index] .title.rangeOfString(“cajero”)!= nil {line。

我在for循环开始之后添加了一个println(“(currentMakers.count)”),我看到它有点打印垃圾。它打印了很多1,然后是2,然后是3,直到8,然后是:

8
8
8
8
8
10
10
10
10
1100

1100

1100

1100

1100

1100

10
11
11
11
11

在出错时,index为2,currentMakers.count为30。

1 个答案:

答案 0 :(得分:0)

您可以非常轻松地重构该代码,而不需要在数组中修改GMSMarker实例 - 这应该消除您所看到的任何线程问题:

var thisLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(latitude, longitude)
let marker = GMSMarker(position: thisLocation)

var calle = obj["calle"] as String
var numero = obj["numero"] as String
var colonia = obj["colonia"] as String
var direccion = "\(calle) \(numero), \(colonia)"
var horarioSemanal = obj["horario_lv"] as String
var horarioSabatino = obj["horario_s"] as String
var nombre = obj["sucursal"] as String

marker.icon = UIImage(named: tipo.lowercaseString)
marker.title = "\(tipo) - \(nombre)"
marker.appearAnimation = kGMSMarkerAnimationPop
marker.snippet = dirección
currentMarkers.append(marker)