0

I am using Xcode 8.3 and Swift 3.0. This is my first attempt at using Swift after going through the Jump Right In tutorial provided by Apple.

I have a data model file that defines a class:

class Location: NSObject, NSCoding {

    //MARK: Properties

    var name: String
    var number: Int
    var item: String
    var visited: Bool
    var coords: [Coordinates]

    //MARK: Types

    struct Coordinates {
        // default values are for a location
        let latitude: Double = 35.0
        let longitude: Double = -120.0
    }

    //MARK: Initialization

    init(name: String, number: Int, item: String, visited: Bool, coords: [Coordinates]) {

        // Initialize stored properties
        self.name = name
        self.number = number
        self.item = item
        self.visited = visited
        self.coords = coords
    }
}

I also have a ViewController that I want to use the data in. Right now, I'm still writing/learning, so I'm having it load a sample piece of data that I enter by hand:

class ViewController: UIViewController {

    //MARK: Properties
    // an array of the locations
    var locations = [Location]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load a sample location.
        locations[0] = Location(name: "foo", number: 1, item: "bar", visited: false, coords: [Location.Coordinates(latitude: 36.0, longitude: -121.0)])
        os_log("Locations successfully loaded on map screen.", log: OSLog.default, type: .debug)
    }
}

The problem part is clearly coords: [Location.Coordinates(latitude: 36.0, longitude: -121.0)], which I added after the code was otherwise functioning. The error Xcode gives me is:

Cannot invoke value of type 'Location.Coordinates.Type' with argument list '(latitude: Double, longitude: Double)'

When I search for this error, I find this question, which looks very similar to me. So, I do as the accepted answer says:

  • I create an instance of the Coordinates type in the Location class (adding var instanceOfCoordinates = Coordinates() after the definition of Coordinates)

  • I also create an instance of the Location class in the ViewController class (adding let instanceOfLocation = Location.self after declaring the locations property)

  • I update the problematic bit of code to coords: [instanceOfLocation.instanceOfCoordinates(latitude: 36.0, longitude: -121.0)]

I get a different error:

Instance member 'instanceOfCoordinates' cannot be used on type 'Location'

EDIT: Adding [] around the part of the code after coords: but before the last ) doesn't change the errors.

What I want is be able to keep the coordinates as a structure within the location so that they are always together and I can use dot referencing to get the values in the form locations[0].coords[index].latitiude and locations[25].coords[index].longitude and so on. Eventually this will be used to populate a google map with pins.

I am sure there are a great many subtleties (and not so subtle) of Swift lost on me, but usually searching and tinkering works out, but not this time.

Can someone please demonstrate what I'm doing wrong here?

Community
  • 1
  • 1
Finncent Price
  • 543
  • 1
  • 8
  • 20
  • 1
    Your initialiser wants an array of coordinates, so wrap `[]` around `Location.Coordinates()` and add .0 to the end of your numeric values so that they are doubles or use `Double(36)`. FYI, making the structure a child of your class won't let you use the syntax you specify in the last part of your question. It would still be `location[0].coords[someIndex].latitude` – Paulw11 Apr 17 '17 at 00:55
  • Also, it doesn't make sense to initialise your struct members with default values and you could use the existing `CLLocationCoordinate2D` rather that reinventing the wheel. – Paulw11 Apr 17 '17 at 01:01
  • Thanks for the response @Paulw11, I have made the changes you mentioned. Most were because I edited the text to be more compact for display here, but they nonetheless improve my question. Unfortunately, they do not change either of the errors. – Finncent Price Apr 17 '17 at 02:07

1 Answers1

1

You can't simply assign to element 0 of your empty locations array; you can use .append to append the new item to the array.

There are a few other changes I would suggest:

  • Don't initialise your Coordinates struct with default values. The initialiser will take care of initialising for you.
  • The Coordinates struct should be Coordinate - singular.

class Location: NSObject, NSCoding {

    //MARK: Properties

    var name: String
    var number: Int
    var item: String
    var visited: Bool
    var coords: [Coordinate]

    //MARK: Types

    struct Coordinate {
        // default values are for a location
        let latitude: Double 
        let longitude: Double = 
    }

    //MARK: Initialization

    init(name: String, number: Int, item: String, visited: Bool, coords: [Coordinates]) {

        // Initialize stored properties
        self.name = name
        self.number = number
        self.item = item
        self.visited = visited
        self.coords = coords
    }
}

class ViewController: UIViewController {

    //MARK: Properties
    // an array of the locations
    var locations = [Location]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Load a sample location.

        locations.append(Location(name: "foo", number: 1, item: "bar", visited: false, coords: [Location.Coordinates(latitude: 36.0, longitude: -121.0)]))
    }
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Deleting the default values in the structure appears to have fixed the problem. Why did that cause this issue? Also, do you want me to change coordinates to coordinate as a matter of preference, or is it what a Swift-person would expect to see? – Finncent Price Apr 17 '17 at 02:50
  • They are `let` constants, so once they have a value you can't assign another value. `Coordinate` is just grammatically correct, so it reads better. The struct represents a single coordinate, not multiple coordinates – Paulw11 Apr 17 '17 at 03:27
  • Coordinates is grammatically correct. A latitude is a coordinate, a longitude is a coordinate and a set containing a latitude and a longitude is a set of coordinate**s**. In 15 years in science I have never heard anyone use "coordinate" for a set of two (or more) numbers. As to the `let`, I thought that when you instantiate an instance of a structure that it ignored the defaults. I'm not sure where I got that from, but it is clearly wrong! – Finncent Price Apr 19 '17 at 04:02