2

I am new to Swift language. I've created a MapKit app that retrieves MKPointAnnotation data (lat, log and title) recursively from a Sqlite DB (latest FMDB stack).

The purpose is to put a bunch of interest points on a MKMapViewDelegate. I've tried w/out an array but the mapView.addAnnotation overwrites any point and shows only the last one on the map, so I'm trying with an array.

I've create a function, but I get the error "fatal error: Cannot index empty buffer" in runtime when wpoint array is called.

Here's the code:

func initializeRoute()
{

    sharedInstance.database!.open()
    var resultSet: FMResultSet! = sharedInstance.database!.executeQuery("SELECT * FROM Route", withArgumentsInArray: nil)

    // DB Structure

    var DBorder:        String = "order"        // Int and Primary Index
    var DBlatitude:     String = "latitude"     // Float
    var DBlongitude:    String = "longitude"    // Float

    // Array declaration
    var wpoint: [MKPointAnnotation] = []

    // Loop counter init
    var counter: Int = 0

    if (resultSet != nil) {
        while resultSet.next() {
            counter = counter + 1

            wpoint[counter].coordinate = CLLocationCoordinate2DMake(
                (resultSet.stringForColumn(String(DBlatitude)) as NSString).doubleValue,
                (resultSet.stringForColumn(String(DBlongitude)) as NSString).doubleValue
            )
            wpoint[counter].title = resultSet.stringForColumn(DBorder)
            mapView.addAnnotation(wpoint[counter])

        }
    }

    sharedInstance.database!.close()

}

println ("Coordinate = \(wpoint.coordinate)") show all data, I'm messing something within array declaration...

Max Uggeri
  • 21
  • 3

1 Answers1

3

The array declaration:

var wpoint: [MKPointAnnotation] = []

creates an empty array (zero elements).

Then, as the Swift documentation says:

It is not possible to insert additional items into the array using subscripting:

which is why you get the "fatal error: Cannot index empty buffer" error later on this line:

wpoint[counter].coordinate = ...


Instead, as the documentation also says, use the append method or the += operator.

Either way, you'll need to create an MKPointAnnotation object at each iteration, set its properties, add it to the array, and then pass it to addAnnotation. For example:

var wpoint: [MKPointAnnotation] = []

if (resultSet != nil) {
    while resultSet.next() {

        let pa = MKPointAnnotation()

        pa.coordinate = CLLocationCoordinate2DMake(
            (resultSet.stringForColumn(String(DBlatitude)) as NSString).doubleValue,
            (resultSet.stringForColumn(String(DBlongitude)) as NSString).doubleValue
        )

        pa.title = resultSet.stringForColumn(DBorder)

        wpoint.append(pa)
        //wpoint += [pa]  //alternative way to add object to array

        mapView.addAnnotation(pa)
    }
}

Please note a few additional things:

  1. The wpoint array is not really necessary in the first place since you are adding annotations one at a time using addAnnotation (singular) and the code is not doing anything else with wpoint.
  2. If you really want to use wpoint and add annotations to the map "all at once", then in the loop, you should add the annotations only to the array and then after the loop, call addAnnotations (plural) once and pass it the whole array.
  3. The original code which used counter as the array index was assuming that the first index was 1 (counter was initialized to 0 but it is incremented at the top of the loop). In Swift and many other languages, array indexes are zero-based.
  4. A minor point but the code in the question is not "recursively" retrieving data. It is retrieving the data iteratively. Recursively would be if, for example, the initializeRoute method called itself.