0

Whilst debugging I can see that the fixtureList in the controller returns 6 values. However, when the code jumps into the fixtureView.update(...) within the View, the fixtureList value is 0.

I'm sure it's something to do with creating the same variable in both controller and view, but can't figure it out!

What would be the best way to resolve this issue? Esentially I want the 6 values to be received by the View so that the user interface can be populated.

Controller

var fixtureList = [Fixture]()

func updateScores() {
    liveScoreApi.fetchFixtures() { (
        isOK, fixture) in
        if isOK == true {
                for fixture in (fixture?.fixtures)! {
                    self.fixtureList.append(fixture)
                 }
            self.fixtureView.update(/*dump*/(self.fixtureList))
            }
        else {
            NSLog("error fetching!")
        }
    }
}

View

class FixtureView: NSView {

@IBOutlet weak var homeNameTextField: NSTextField!
@IBOutlet weak var timeTextField: NSTextField!
@IBOutlet weak var awayNameTextField: NSTextField!

let fixtureList = [Fixture]()

func update(_ fixture: [Fixture]) {
    // do UI updates on the main thread
    DispatchQueue.main.async {
        for fixture in self.fixtureList {
                self.homeNameTextField.stringValue = fixture.homeName
                self.timeTextField.stringValue = fixture.time
                self.awayNameTextField.stringValue = fixture.awayName
                print("added \(fixture.homeName)")
            }
        }
    }
}
baze
  • 23
  • 5
  • If you break on DispatchQueue, is your fixture parameter empty as well? Shouldn't you be iterating over that value? – Dan Beaulieu Jun 04 '18 at 18:10
  • Added break to DispatchQueue - `fixture` has 6 values. You might be right actually, how would I implement this? – baze Jun 04 '18 at 18:25

1 Answers1

1

Your update method should look like this:

//let fixtureList = [Fixture]() // you don't need this

func update(_ fixtureList: [Fixture]) {
    // do UI updates on the main thread
    DispatchQueue.main.async {
        // (though you probably don't want this ultimately)
        for fixture in fixtureList {
            self.homeNameTextField.stringValue = fixture.homeName
            self.timeTextField.stringValue = fixture.time
            self.awayNameTextField.stringValue = fixture.awayName
            print("added \(fixture.homeName)") 
        }
    }
}

The problem is that you are newing up an array of Fixture objects at the class level. Then, inside your update method, you are attempting to iterate over the new array rather than your passed in array.

  • Just eliminate the unnecessary array at the class level.
  • change the name of your parameter to fixtureList
  • remove self. from fixtureList your for in loop
Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
  • Ah yes, that's perfect. Cheers! Makes sense. Probably a separate question, but any idea why only the last value in `fixtureList` is displayed on the UI? – baze Jun 04 '18 at 18:34
  • Oh yeah, for sure. So think about what this for loop is doing. Each time it iterates its setting your three labels to the current iteration's value over writing the previous value. So, naturally, whatever the last value that was iterated over, will be the only thing that you see. Let me know if that makes sense @baze – Dan Beaulieu Jun 04 '18 at 18:36
  • Of course, yeah that's it. I'll have a go at resolving this. Although if I remove the loop, to access the homeName for example I need to specify an index: `self.homeNameTextField.stringValue = fixtureList[1].homeName`. But I want to update all homeNames, not just `[1]` – baze Jun 04 '18 at 18:43
  • @baze Should you be using a table view for this situation? If you feel like you are on the correct path, you can get the iterator like this : https://stackoverflow.com/a/24028458/1664443 – Dan Beaulieu Jun 04 '18 at 18:46
  • Potentially yes, it sounds like that may be better suited. Although I'm not sure! I'm creating a menu bar app which currently has those 3 labels on. Thanks, I'll take a look – baze Jun 04 '18 at 18:56
  • Cool, so I've got the iterator: `for (index, fixture) in fixtureList.enumerated() {` - if I'm going down this path, how would I then return all iterations to the labels? @DanBeaulieu – baze Jun 04 '18 at 19:40
  • @baze I'm not entirely sure I understand what you're attempting to do. It looks like you want the labels to repeat. For example, each loop iteration you want the entire set of labels repeated. So if you have 6 fixtures, you need 6 entire sets of labels. I can think of a way to do this but I'd really advise you switch to a Table View. I made a video a while back that shows how to set up a table view with sections. https://youtu.be/P-27_-zAZgU The sections are optional. – Dan Beaulieu Jun 04 '18 at 20:12
  • Cool, yeah that makes sense to be honest. I’ll give your video a watch and give it a go! – baze Jun 04 '18 at 20:17
  • Have looked at adding a table view now. Think I'm reasonably close, but getting `Cannot assign value of type 'Fixture' to type 'String'`. I'm guessing this means I need declare Fixture as String somewhere, but I'm going round in circles! @DanBeaulieu – baze Jun 09 '18 at 10:01