0

I've written the code below and always get the error

(1) Variable self.pointOnMap used before being initialised.

and

(2) Variable self.pointOnMap captured by a closure before being initialised.

I don't see why because I have declared self.pointOnMap = MKPointAnnotation() which should initialise it early enough.

class Pin: NSManagedObject {
    var mapView: MKMapView?
    var pointOnMap: MKPointAnnotation?

    @NSManaged var lat: Double
    @NSManaged var lon: Double
    @NSManaged var photos: Photo?

    override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
        super.init(entity: entity, insertIntoManagedObjectContext: context)
        self.pointOnMap = MKPointAnnotation()
    }

    init(dictionary: [String : AnyObject], context: NSManagedObjectContext) {
        let entity = NSEntityDescription.entityForName("Pin", inManagedObjectContext: context)!
        super.init(entity: entity, insertIntoManagedObjectContext: context)

        lat = 1.0
        lon = 2.0

        self.pointOnMap = MKPointAnnotation()
        println(self.pointOnMap) // RETURNS ERROR (1)
        self.pointOnMap!.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon) // RETURNS ERROR (2)
    }
user3573256
  • 219
  • 1
  • 2
  • 12
  • see http://stackoverflow.com/questions/27028813/error-in-swift-class-property-not-initialized-at-super-init-call-how-to-initi – Volker Apr 25 '15 at 09:55
  • for what line does it show this error? – Kostiantyn Koval Apr 25 '15 at 10:02
  • println(self.pointOnMap) // RETURNS ERROR (1) self.pointOnMap!.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon) // RETURNS ERROR (2) – user3573256 Apr 25 '15 at 10:03
  • @Volker Making it an implicitly unwrapped optional as suggested in the link doesn't work either. – user3573256 Apr 25 '15 at 10:04
  • have you looked at the link, the order of calls in init is different! I don't have the official documentation at hand, but i remember there was something like that mentioned as well. – Volker Apr 25 '15 at 11:09
  • In the second init, you call super but you're not overriding anything. Plus, you're using the other init signature. Didn't you mean to use self.init(entity: entity, insertIntoManagedObjectContext: context) instead? (self.init instead of super.init). You would also make this 2nd init a convenience init. – Eric Aya Apr 25 '15 at 11:20

1 Answers1

0

I can't reproduce your setup, so I can't test with your exact example, but I think you should use a convenience initializer and self.init like this:

class Pin: NSManagedObject {
    var mapView: MKMapView?
    var pointOnMap: MKPointAnnotation?
    @NSManaged var lat: Double
    @NSManaged var lon: Double
    @NSManaged var photos: Photo?

    override init(entity: NSEntityDescription, insertIntoManagedObjectContext context: NSManagedObjectContext?) {
        super.init(entity: entity, insertIntoManagedObjectContext: context)
        self.pointOnMap = MKPointAnnotation()
    }

    // Replace `init` with `convenience init`
    convenience init(dictionary: [String : AnyObject], context: NSManagedObjectContext) {

        let entity = NSEntityDescription.entityForName("Pin", inManagedObjectContext: context)!

        // Call the overriding init with `self.init(...)` instead of `super.init(...)`
        self.init(entity: entity, insertIntoManagedObjectContext: context)

        // Now, self.pointOnMap has the value declared by `override init`

        lat = 1.0
        lon = 2.0

        self.pointOnMap = MKPointAnnotation()
        println(self.pointOnMap)
        self.pointOnMap!.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
    }
}

Have a look at "Designated and Convenience Initializers in Action" in this page, I think it covers your case.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253