2

I'm trying to init an array of Int in my custom UIView:

var graphPoints:[Int]

required init?(coder aDecoder: NSCoder) {
    RestApiManager.sharedInstance.requestData() { (json: JSON) in
        for item in json[].array! {
            let n=item["n"].intValue
            print(n)
            if(n>=0) {
                self.graphPoints.append(n)
            }
        }
    }
    super.init(coder: aDecoder)
}

But int this row RestApiManager.sharedInstance.requestData() { i reiceved this error: 'self' used before super.init call

And at this row super.init(coder: aDecoder) the error: property self.graphPoint not initialized at super.init call

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Matteo Serpentoni
  • 553
  • 1
  • 7
  • 19
  • 1
    Possible duplicate of [Error in Swift class: Property not initialized at super.init call](http://stackoverflow.com/questions/24021093/error-in-swift-class-property-not-initialized-at-super-init-call) – tbilopavlovic Jun 06 '16 at 22:20
  • I think that you need put `super.init(coder: aDecoder)`before of your other code and, the second issue I think that has been resolved by @user1941284 – Reinier Melian Jun 06 '16 at 22:21
  • 3
    Putting an asynchronous network call in `init` is a bad idea – Paulw11 Jun 06 '16 at 22:23
  • @Paulw11 where i put asynchronous network? – Matteo Serpentoni Jun 06 '16 at 22:27
  • 1
    There are lots of ways. I would probably create a class that encapsulated the server API. It would have a method that made the request and returned via a closure an instance of whatever this class is. Or since this is a UIView subclass you could define a setter on `graphPoints` that update the view, with the data being retrieved somewhere else. It is a poor design to tightly couple a view and a server API – Paulw11 Jun 06 '16 at 22:30

3 Answers3

2

There are a few seperate issues here

The first related two you question being that you must call the super.init method before you reference self. Simply move this line to the beginning on the init method.

Unfortunately because you are preforming an asynchronous request this will still cause you problems as mentioned in the comments.

Also, note init?(coder aDecoder: NSCoder) is not intended for this use. Another issue is if you are requesting data from your API you should create a model object. As opposed to directly creating a UIView and then when you wish to display it to a user create a UIView from that model.

class GraphPointsModel {
  var graphPoints:[Int]

  init(graphPoints: [Int]) {
    self.graphPoints = graphPoints
  }

  class func retreiveGraphPoints(handler: (GraphPointsModel -> ())) {
    RestApiManager.sharedInstance.requestData() { (json: JSON) in
      //Error checking...

      //Create instance of GraphPointsModel
      let instance = GraphPointsModel(...)  

      //Call handler to do with as you wish with result
      handler(instance)
    }
  }

}
Blake Lockley
  • 2,931
  • 1
  • 17
  • 30
  • In my current project, putting `self.init()` in an asynchronous completion block led to mystery compiling errors - segmentation signals 9 and/or 11. Clearly the path to the dark side. Fixed by using `DispatchQueue.main.sync { <#code#> }` – AmitaiB Jan 25 '17 at 04:30
1

Swift requires all parameters to be initialized before calling super.init(). There are several ways to make this happen.

Declare graphPoints with an empty initializer like this:

var graphPoints:[Int] = []   or var graphPoints = [Int]()

You can also change the graphPoints to an Optional, like this:

var graphPoints:[Int]?

You can also leave the declaration alone, and just initialize it to an empty array before calling super.init()

You will also need to move your RestAPI call below your super.init call.

Hope this helps.

DJohnson
  • 929
  • 4
  • 15
-1

Maybe you must to do this:

super.init(coder: aDecoder)

put that before your requestData call.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Vlad
  • 7
  • 1
  • 1
    this call `self = super.init(coder: aDecoder)` on swift, make an error "Cannot assign to value: 'self' is immutable" jump from compiler – Reinier Melian Jun 06 '16 at 22:56