Index out of range error even though number of values matches number of rows





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I'm trying to set some images to image views in a tableview, and I have the number of rows set to return keys.count, which after printing is confirmed to be 5, which is perfect.



Now in cellForRowAt I get the images in an array, then attempt to set the images to my cell's image view.



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "stockCell", for: indexPath) as! StockCell

let stock = stockData[keys[indexPath.row]]!

var images = [String]()
stock.news.forEach { images.append($0.image) }
print("nnNumber of Images: (images.count)nnn")

if let companyImageUrl = URL(string: images[indexPath.row]) {
ImageService.getImage(url: companyImageUrl) { (image) in
cell.companyLogoImageView.image = image
}
}

return cell
}
}


I put a print statement in there to print the images.count (there should be 5), but the console shows 2, then 5 (x3), then 2 again - this is causing the index out of range error presumably, it's seeing 2 when there should be 5:



enter image description here



Why is images.count showing 2 in the first and last spots, but 5 in the rest?



EDIT: Rest of code



Fetching the data (in viewDidLoad):



    fetchData(url: stockApiUrl) { (result: FetchResult<[String:Stock]>) -> (Void) in
switch result {
case .success(let object):
self.stockData = object
self.keys = Array(object.keys)
print("stockData: nn(self.stockData)")
case .failure(let error):
print("Error decoding JSON: nn(error)")
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}


Data is set to a dictionary, with a separate array for the keys:



var stockData = [String:Stock]()
var keys = [String]()


Structs for decoding JSON:



struct Welcome: Decodable {
let aapl, fb, msft, tsla, goog: Stock

enum CodingKeys: String, CodingKey {
case aapl = "AAPL"
case fb = "FB"
case msft = "MSFT"
case tsla = "TSLA"
case goog = "GOOG"
}
}

struct Stock: Decodable {
let quote: Quote
let news: [News]
}

struct Quote: Decodable {
let symbol: String
let companyName: String
let latestPrice: Double
}

struct News: Decodable {
let url: String
let image: String
}









share|improve this question

























  • I don't get it, how are we supposed to know what stock.news contains?

    – Joakim Danielson
    Nov 16 '18 at 17:45











  • Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

    – KingTim
    Nov 16 '18 at 17:48


















0















I'm trying to set some images to image views in a tableview, and I have the number of rows set to return keys.count, which after printing is confirmed to be 5, which is perfect.



Now in cellForRowAt I get the images in an array, then attempt to set the images to my cell's image view.



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "stockCell", for: indexPath) as! StockCell

let stock = stockData[keys[indexPath.row]]!

var images = [String]()
stock.news.forEach { images.append($0.image) }
print("nnNumber of Images: (images.count)nnn")

if let companyImageUrl = URL(string: images[indexPath.row]) {
ImageService.getImage(url: companyImageUrl) { (image) in
cell.companyLogoImageView.image = image
}
}

return cell
}
}


I put a print statement in there to print the images.count (there should be 5), but the console shows 2, then 5 (x3), then 2 again - this is causing the index out of range error presumably, it's seeing 2 when there should be 5:



enter image description here



Why is images.count showing 2 in the first and last spots, but 5 in the rest?



EDIT: Rest of code



Fetching the data (in viewDidLoad):



    fetchData(url: stockApiUrl) { (result: FetchResult<[String:Stock]>) -> (Void) in
switch result {
case .success(let object):
self.stockData = object
self.keys = Array(object.keys)
print("stockData: nn(self.stockData)")
case .failure(let error):
print("Error decoding JSON: nn(error)")
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}


Data is set to a dictionary, with a separate array for the keys:



var stockData = [String:Stock]()
var keys = [String]()


Structs for decoding JSON:



struct Welcome: Decodable {
let aapl, fb, msft, tsla, goog: Stock

enum CodingKeys: String, CodingKey {
case aapl = "AAPL"
case fb = "FB"
case msft = "MSFT"
case tsla = "TSLA"
case goog = "GOOG"
}
}

struct Stock: Decodable {
let quote: Quote
let news: [News]
}

struct Quote: Decodable {
let symbol: String
let companyName: String
let latestPrice: Double
}

struct News: Decodable {
let url: String
let image: String
}









share|improve this question

























  • I don't get it, how are we supposed to know what stock.news contains?

    – Joakim Danielson
    Nov 16 '18 at 17:45











  • Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

    – KingTim
    Nov 16 '18 at 17:48














0












0








0








I'm trying to set some images to image views in a tableview, and I have the number of rows set to return keys.count, which after printing is confirmed to be 5, which is perfect.



Now in cellForRowAt I get the images in an array, then attempt to set the images to my cell's image view.



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "stockCell", for: indexPath) as! StockCell

let stock = stockData[keys[indexPath.row]]!

var images = [String]()
stock.news.forEach { images.append($0.image) }
print("nnNumber of Images: (images.count)nnn")

if let companyImageUrl = URL(string: images[indexPath.row]) {
ImageService.getImage(url: companyImageUrl) { (image) in
cell.companyLogoImageView.image = image
}
}

return cell
}
}


I put a print statement in there to print the images.count (there should be 5), but the console shows 2, then 5 (x3), then 2 again - this is causing the index out of range error presumably, it's seeing 2 when there should be 5:



enter image description here



Why is images.count showing 2 in the first and last spots, but 5 in the rest?



EDIT: Rest of code



Fetching the data (in viewDidLoad):



    fetchData(url: stockApiUrl) { (result: FetchResult<[String:Stock]>) -> (Void) in
switch result {
case .success(let object):
self.stockData = object
self.keys = Array(object.keys)
print("stockData: nn(self.stockData)")
case .failure(let error):
print("Error decoding JSON: nn(error)")
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}


Data is set to a dictionary, with a separate array for the keys:



var stockData = [String:Stock]()
var keys = [String]()


Structs for decoding JSON:



struct Welcome: Decodable {
let aapl, fb, msft, tsla, goog: Stock

enum CodingKeys: String, CodingKey {
case aapl = "AAPL"
case fb = "FB"
case msft = "MSFT"
case tsla = "TSLA"
case goog = "GOOG"
}
}

struct Stock: Decodable {
let quote: Quote
let news: [News]
}

struct Quote: Decodable {
let symbol: String
let companyName: String
let latestPrice: Double
}

struct News: Decodable {
let url: String
let image: String
}









share|improve this question
















I'm trying to set some images to image views in a tableview, and I have the number of rows set to return keys.count, which after printing is confirmed to be 5, which is perfect.



Now in cellForRowAt I get the images in an array, then attempt to set the images to my cell's image view.



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "stockCell", for: indexPath) as! StockCell

let stock = stockData[keys[indexPath.row]]!

var images = [String]()
stock.news.forEach { images.append($0.image) }
print("nnNumber of Images: (images.count)nnn")

if let companyImageUrl = URL(string: images[indexPath.row]) {
ImageService.getImage(url: companyImageUrl) { (image) in
cell.companyLogoImageView.image = image
}
}

return cell
}
}


I put a print statement in there to print the images.count (there should be 5), but the console shows 2, then 5 (x3), then 2 again - this is causing the index out of range error presumably, it's seeing 2 when there should be 5:



enter image description here



Why is images.count showing 2 in the first and last spots, but 5 in the rest?



EDIT: Rest of code



Fetching the data (in viewDidLoad):



    fetchData(url: stockApiUrl) { (result: FetchResult<[String:Stock]>) -> (Void) in
switch result {
case .success(let object):
self.stockData = object
self.keys = Array(object.keys)
print("stockData: nn(self.stockData)")
case .failure(let error):
print("Error decoding JSON: nn(error)")
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}


Data is set to a dictionary, with a separate array for the keys:



var stockData = [String:Stock]()
var keys = [String]()


Structs for decoding JSON:



struct Welcome: Decodable {
let aapl, fb, msft, tsla, goog: Stock

enum CodingKeys: String, CodingKey {
case aapl = "AAPL"
case fb = "FB"
case msft = "MSFT"
case tsla = "TSLA"
case goog = "GOOG"
}
}

struct Stock: Decodable {
let quote: Quote
let news: [News]
}

struct Quote: Decodable {
let symbol: String
let companyName: String
let latestPrice: Double
}

struct News: Decodable {
let url: String
let image: String
}






ios swift uitableview






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 16 '18 at 18:17









rmaddy

247k27328391




247k27328391










asked Nov 16 '18 at 17:39









KingTimKingTim

5261821




5261821













  • I don't get it, how are we supposed to know what stock.news contains?

    – Joakim Danielson
    Nov 16 '18 at 17:45











  • Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

    – KingTim
    Nov 16 '18 at 17:48



















  • I don't get it, how are we supposed to know what stock.news contains?

    – Joakim Danielson
    Nov 16 '18 at 17:45











  • Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

    – KingTim
    Nov 16 '18 at 17:48

















I don't get it, how are we supposed to know what stock.news contains?

– Joakim Danielson
Nov 16 '18 at 17:45





I don't get it, how are we supposed to know what stock.news contains?

– Joakim Danielson
Nov 16 '18 at 17:45













Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

– KingTim
Nov 16 '18 at 17:48





Sorry I wasn't sure if that part was necessary, I edited my question to add the rest of the code.

– KingTim
Nov 16 '18 at 17:48












2 Answers
2






active

oldest

votes


















0














Add another print and make sure that the quantity of news is also different for each row. Then find out why it is different.



stock.news.forEach { images.append($0.image) }
print("nnNumber of Images: (images.count)nnn")
print("nnNumber of stock.news: (stock.news.count)nnn")





share|improve this answer
























  • Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

    – KingTim
    Nov 16 '18 at 18:11













  • This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

    – rmaddy
    Nov 16 '18 at 18:17













  • Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

    – Sergey
    Nov 16 '18 at 18:22





















0














You are assuming that you have 5 images because keys.count is 5 and this is wrong since keys.count tells you that you have 5 stocks in the dictionary you created from the json message.



Now each stock has an news array attached to it that I assume contains news articles/messages related to the stock for one day or similar so this array could then contain from 0 up to an infinite (not likely) amount of news articles. (in this case the number of articles ranges between 2 and 5).



Anyway, you can not rely on keys.count when reading the news array but instead for each array check news.count.



So this code needs to be changed but I am not sure how



if let companyImageUrl = URL(string: images[indexPath.row]) {
ImageService.getImage(url: companyImageUrl) { (image) in
cell.companyLogoImageView.image = image
}
}


Will you show all images? then you need to surround this with a loop somehow but I get the feeling you only want to show one image so maybe change URL(string: images[indexPath.row]) to URL(string: images[0])






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53342835%2findex-out-of-range-error-even-though-number-of-values-matches-number-of-rows%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    Add another print and make sure that the quantity of news is also different for each row. Then find out why it is different.



    stock.news.forEach { images.append($0.image) }
    print("nnNumber of Images: (images.count)nnn")
    print("nnNumber of stock.news: (stock.news.count)nnn")





    share|improve this answer
























    • Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

      – KingTim
      Nov 16 '18 at 18:11













    • This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

      – rmaddy
      Nov 16 '18 at 18:17













    • Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

      – Sergey
      Nov 16 '18 at 18:22


















    0














    Add another print and make sure that the quantity of news is also different for each row. Then find out why it is different.



    stock.news.forEach { images.append($0.image) }
    print("nnNumber of Images: (images.count)nnn")
    print("nnNumber of stock.news: (stock.news.count)nnn")





    share|improve this answer
























    • Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

      – KingTim
      Nov 16 '18 at 18:11













    • This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

      – rmaddy
      Nov 16 '18 at 18:17













    • Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

      – Sergey
      Nov 16 '18 at 18:22
















    0












    0








    0







    Add another print and make sure that the quantity of news is also different for each row. Then find out why it is different.



    stock.news.forEach { images.append($0.image) }
    print("nnNumber of Images: (images.count)nnn")
    print("nnNumber of stock.news: (stock.news.count)nnn")





    share|improve this answer













    Add another print and make sure that the quantity of news is also different for each row. Then find out why it is different.



    stock.news.forEach { images.append($0.image) }
    print("nnNumber of Images: (images.count)nnn")
    print("nnNumber of stock.news: (stock.news.count)nnn")






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 16 '18 at 18:08









    SergeySergey

    26




    26













    • Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

      – KingTim
      Nov 16 '18 at 18:11













    • This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

      – rmaddy
      Nov 16 '18 at 18:17













    • Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

      – Sergey
      Nov 16 '18 at 18:22





















    • Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

      – KingTim
      Nov 16 '18 at 18:11













    • This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

      – rmaddy
      Nov 16 '18 at 18:17













    • Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

      – Sergey
      Nov 16 '18 at 18:22



















    Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

    – KingTim
    Nov 16 '18 at 18:11







    Ok, printing stock.news.count shows the same irregularity as images.count, except now both counts are 5, 5, 2, 2, 5.

    – KingTim
    Nov 16 '18 at 18:11















    This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

    – rmaddy
    Nov 16 '18 at 18:17







    This isn't an answer, this is a debugging comment. Please wait until you have enough reputation to post comments.

    – rmaddy
    Nov 16 '18 at 18:17















    Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

    – Sergey
    Nov 16 '18 at 18:22







    Ok. But I thought it was. The question: "Why is images.count showing 2 in the first and last spots, but 5 in the rest?" And the answer: "because stock.news is different in each row".

    – Sergey
    Nov 16 '18 at 18:22















    0














    You are assuming that you have 5 images because keys.count is 5 and this is wrong since keys.count tells you that you have 5 stocks in the dictionary you created from the json message.



    Now each stock has an news array attached to it that I assume contains news articles/messages related to the stock for one day or similar so this array could then contain from 0 up to an infinite (not likely) amount of news articles. (in this case the number of articles ranges between 2 and 5).



    Anyway, you can not rely on keys.count when reading the news array but instead for each array check news.count.



    So this code needs to be changed but I am not sure how



    if let companyImageUrl = URL(string: images[indexPath.row]) {
    ImageService.getImage(url: companyImageUrl) { (image) in
    cell.companyLogoImageView.image = image
    }
    }


    Will you show all images? then you need to surround this with a loop somehow but I get the feeling you only want to show one image so maybe change URL(string: images[indexPath.row]) to URL(string: images[0])






    share|improve this answer




























      0














      You are assuming that you have 5 images because keys.count is 5 and this is wrong since keys.count tells you that you have 5 stocks in the dictionary you created from the json message.



      Now each stock has an news array attached to it that I assume contains news articles/messages related to the stock for one day or similar so this array could then contain from 0 up to an infinite (not likely) amount of news articles. (in this case the number of articles ranges between 2 and 5).



      Anyway, you can not rely on keys.count when reading the news array but instead for each array check news.count.



      So this code needs to be changed but I am not sure how



      if let companyImageUrl = URL(string: images[indexPath.row]) {
      ImageService.getImage(url: companyImageUrl) { (image) in
      cell.companyLogoImageView.image = image
      }
      }


      Will you show all images? then you need to surround this with a loop somehow but I get the feeling you only want to show one image so maybe change URL(string: images[indexPath.row]) to URL(string: images[0])






      share|improve this answer


























        0












        0








        0







        You are assuming that you have 5 images because keys.count is 5 and this is wrong since keys.count tells you that you have 5 stocks in the dictionary you created from the json message.



        Now each stock has an news array attached to it that I assume contains news articles/messages related to the stock for one day or similar so this array could then contain from 0 up to an infinite (not likely) amount of news articles. (in this case the number of articles ranges between 2 and 5).



        Anyway, you can not rely on keys.count when reading the news array but instead for each array check news.count.



        So this code needs to be changed but I am not sure how



        if let companyImageUrl = URL(string: images[indexPath.row]) {
        ImageService.getImage(url: companyImageUrl) { (image) in
        cell.companyLogoImageView.image = image
        }
        }


        Will you show all images? then you need to surround this with a loop somehow but I get the feeling you only want to show one image so maybe change URL(string: images[indexPath.row]) to URL(string: images[0])






        share|improve this answer













        You are assuming that you have 5 images because keys.count is 5 and this is wrong since keys.count tells you that you have 5 stocks in the dictionary you created from the json message.



        Now each stock has an news array attached to it that I assume contains news articles/messages related to the stock for one day or similar so this array could then contain from 0 up to an infinite (not likely) amount of news articles. (in this case the number of articles ranges between 2 and 5).



        Anyway, you can not rely on keys.count when reading the news array but instead for each array check news.count.



        So this code needs to be changed but I am not sure how



        if let companyImageUrl = URL(string: images[indexPath.row]) {
        ImageService.getImage(url: companyImageUrl) { (image) in
        cell.companyLogoImageView.image = image
        }
        }


        Will you show all images? then you need to surround this with a loop somehow but I get the feeling you only want to show one image so maybe change URL(string: images[indexPath.row]) to URL(string: images[0])







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 16 '18 at 18:56









        Joakim DanielsonJoakim Danielson

        10.8k3725




        10.8k3725






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53342835%2findex-out-of-range-error-even-though-number-of-values-matches-number-of-rows%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Xamarin.iOS Cant Deploy on Iphone

            Glorious Revolution

            Dulmage-Mendelsohn matrix decomposition in Python