Index out of range exception using DispatchQueue
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have the following code which shows a list of quizzes in a UITableView.
The problem is that to show the images I call my method prepareImages
and I get an index out of range exception when filling the cells in tableView
function because it appears that the quizzesImages
array is empty (print(self.quizzesImages.count)
shows 0
), I know it has something to do with how I put the threads to work but I don't see where I am going wrong.
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject : Codable {
let quizzes : [Quiz]?
let pageno : Int?
let nextUrl : String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
for i in 0...self.totalQuizzes.count-1{
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
let imageData:NSData = NSData(contentsOf: imageUrl)!
// When from background thread, UI needs to be updated on main_queue
DispatchQueue.main.async {
let image = UIImage(data: imageData as Data)
print("hola")
self.quizzesImages.append(image!)
}
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
defer{
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
print(self.quizzesImages.count)
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz", for: indexPath) as! QuizTableViewCell
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.authorLabel?.text = quiz.author?.username
cell.quizLabel?.text = quiz.question
cell.quizImage?.image = images
return cell
}}
Thanks in advance for the help!
ios swift grand-central-dispatch
|
show 6 more comments
I have the following code which shows a list of quizzes in a UITableView.
The problem is that to show the images I call my method prepareImages
and I get an index out of range exception when filling the cells in tableView
function because it appears that the quizzesImages
array is empty (print(self.quizzesImages.count)
shows 0
), I know it has something to do with how I put the threads to work but I don't see where I am going wrong.
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject : Codable {
let quizzes : [Quiz]?
let pageno : Int?
let nextUrl : String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
for i in 0...self.totalQuizzes.count-1{
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
let imageData:NSData = NSData(contentsOf: imageUrl)!
// When from background thread, UI needs to be updated on main_queue
DispatchQueue.main.async {
let image = UIImage(data: imageData as Data)
print("hola")
self.quizzesImages.append(image!)
}
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
defer{
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
print(self.quizzesImages.count)
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz", for: indexPath) as! QuizTableViewCell
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.authorLabel?.text = quiz.author?.username
cell.quizLabel?.text = quiz.question
cell.quizImage?.image = images
return cell
}}
Thanks in advance for the help!
ios swift grand-central-dispatch
You check ifesponse.quizzes!.count != 0
is true? Try printresponse.quizzes
– Augusto
Nov 23 '18 at 16:40
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
1
@HarshalBhavsar This is Quiz.swift fileimport Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53
|
show 6 more comments
I have the following code which shows a list of quizzes in a UITableView.
The problem is that to show the images I call my method prepareImages
and I get an index out of range exception when filling the cells in tableView
function because it appears that the quizzesImages
array is empty (print(self.quizzesImages.count)
shows 0
), I know it has something to do with how I put the threads to work but I don't see where I am going wrong.
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject : Codable {
let quizzes : [Quiz]?
let pageno : Int?
let nextUrl : String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
for i in 0...self.totalQuizzes.count-1{
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
let imageData:NSData = NSData(contentsOf: imageUrl)!
// When from background thread, UI needs to be updated on main_queue
DispatchQueue.main.async {
let image = UIImage(data: imageData as Data)
print("hola")
self.quizzesImages.append(image!)
}
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
defer{
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
print(self.quizzesImages.count)
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz", for: indexPath) as! QuizTableViewCell
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.authorLabel?.text = quiz.author?.username
cell.quizLabel?.text = quiz.question
cell.quizImage?.image = images
return cell
}}
Thanks in advance for the help!
ios swift grand-central-dispatch
I have the following code which shows a list of quizzes in a UITableView.
The problem is that to show the images I call my method prepareImages
and I get an index out of range exception when filling the cells in tableView
function because it appears that the quizzesImages
array is empty (print(self.quizzesImages.count)
shows 0
), I know it has something to do with how I put the threads to work but I don't see where I am going wrong.
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject : Codable {
let quizzes : [Quiz]?
let pageno : Int?
let nextUrl : String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
for i in 0...self.totalQuizzes.count-1{
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
let imageData:NSData = NSData(contentsOf: imageUrl)!
// When from background thread, UI needs to be updated on main_queue
DispatchQueue.main.async {
let image = UIImage(data: imageData as Data)
print("hola")
self.quizzesImages.append(image!)
}
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
defer{
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
print(self.quizzesImages.count)
self.tableView.reloadData()
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz", for: indexPath) as! QuizTableViewCell
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.authorLabel?.text = quiz.author?.username
cell.quizLabel?.text = quiz.question
cell.quizImage?.image = images
return cell
}}
Thanks in advance for the help!
ios swift grand-central-dispatch
ios swift grand-central-dispatch
edited Nov 23 '18 at 20:26
zekel
5,17664991
5,17664991
asked Nov 23 '18 at 16:25
martingoldthenmartingoldthen
154
154
You check ifesponse.quizzes!.count != 0
is true? Try printresponse.quizzes
– Augusto
Nov 23 '18 at 16:40
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
1
@HarshalBhavsar This is Quiz.swift fileimport Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53
|
show 6 more comments
You check ifesponse.quizzes!.count != 0
is true? Try printresponse.quizzes
– Augusto
Nov 23 '18 at 16:40
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
1
@HarshalBhavsar This is Quiz.swift fileimport Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53
You check if
esponse.quizzes!.count != 0
is true? Try print response.quizzes
– Augusto
Nov 23 '18 at 16:40
You check if
esponse.quizzes!.count != 0
is true? Try print response.quizzes
– Augusto
Nov 23 '18 at 16:40
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
1
1
@HarshalBhavsar This is Quiz.swift file
import Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53
@HarshalBhavsar This is Quiz.swift file
import Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53
|
show 6 more comments
2 Answers
2
active
oldest
votes
See this screen shot form my playground
I tried to run your code in playground and managed to get it work with some changes please see the following.
Note
To make it run in playground i have to make some assumptions just replace your core logic with my one.
Happy Coding 😀
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject: Codable {
let quizzes: [Quiz]?
let pageno: Int?
let nextURL: String?
enum CodingKeys: String, CodingKey {
case quizzes, pageno
case nextURL = "nextUrl"
}
}
struct Quiz: Codable {
let id: Int?
let question: String?
let author: Author?
let attachment: Attachment?
let favourite: Bool?
let tips: [String]?
}
struct Attachment: Codable {
let filename: String?
let mime: MIME?
let url: String?
}
enum MIME: String, Codable {
case imageJPEG = "image/jpeg"
}
struct Author: Codable {
let id: Int?
let isAdmin: Bool?
let username: String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Quiz")
self.tableView.dataSource = self
self.tableView.delegate = self
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
print("in prepare images")
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
for i in 0...self.totalQuizzes.count-1 {
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
let imageData:NSData = NSData(contentsOf: imageUrl)!
let image = UIImage(data: imageData as Data)
print("hola (i)")
self.quizzesImages.append(image!)
print(self.quizzesImages.count)
// When from background thread, UI needs to be updated on main_queue
}
DispatchQueue.main.async {
print(self.quizzesImages.count)
self.tableView.reloadData()
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
print("num of rows (totalQuizzes.count)")
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("in cellForRowAt (indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz")!
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.textLabel?.text = "(quiz.author?.username) (quiz.question)"
cell.imageView?.image = images
return cell
}}
This worked, I had toself.tableView.reloadData()
onprepareImages
. Thank you very much
– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
add a comment |
Since you didn't say what line the exception is happening on, my best guess is that it's happening on this line.
let images = quizzesImages[indexPath.row]
The issue is in downloadQuizzes
. In there you call prepareImages
then a couple lines later call reloadData
. Since prepareImages
does an async task, it isn't blocking downloadQuizzes
from finishing running. This causes reloadData
to be called before the async part of prepareImages
is finished.
You'll need to make sure prepareImages
is finished running before calling reloadData
.
Another option is to use a library like Kingfisher that will only download the images when they need to be displayed in a cell rather then downloading them all and slowing down showing the table.
Additional Note:
You shouldn't be using Data(contentsOf:)
to load remote content, URLSession
is the correct option for it.
Yes! Taking out all the async tasks inprepareImages
makes it work! How would I do it soreloadData
isn't called untilprepareImages
is done? Thank you so much!
– martingoldthen
Nov 23 '18 at 17:10
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53450085%2findex-out-of-range-exception-using-dispatchqueue%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
See this screen shot form my playground
I tried to run your code in playground and managed to get it work with some changes please see the following.
Note
To make it run in playground i have to make some assumptions just replace your core logic with my one.
Happy Coding 😀
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject: Codable {
let quizzes: [Quiz]?
let pageno: Int?
let nextURL: String?
enum CodingKeys: String, CodingKey {
case quizzes, pageno
case nextURL = "nextUrl"
}
}
struct Quiz: Codable {
let id: Int?
let question: String?
let author: Author?
let attachment: Attachment?
let favourite: Bool?
let tips: [String]?
}
struct Attachment: Codable {
let filename: String?
let mime: MIME?
let url: String?
}
enum MIME: String, Codable {
case imageJPEG = "image/jpeg"
}
struct Author: Codable {
let id: Int?
let isAdmin: Bool?
let username: String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Quiz")
self.tableView.dataSource = self
self.tableView.delegate = self
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
print("in prepare images")
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
for i in 0...self.totalQuizzes.count-1 {
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
let imageData:NSData = NSData(contentsOf: imageUrl)!
let image = UIImage(data: imageData as Data)
print("hola (i)")
self.quizzesImages.append(image!)
print(self.quizzesImages.count)
// When from background thread, UI needs to be updated on main_queue
}
DispatchQueue.main.async {
print(self.quizzesImages.count)
self.tableView.reloadData()
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
print("num of rows (totalQuizzes.count)")
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("in cellForRowAt (indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz")!
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.textLabel?.text = "(quiz.author?.username) (quiz.question)"
cell.imageView?.image = images
return cell
}}
This worked, I had toself.tableView.reloadData()
onprepareImages
. Thank you very much
– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
add a comment |
See this screen shot form my playground
I tried to run your code in playground and managed to get it work with some changes please see the following.
Note
To make it run in playground i have to make some assumptions just replace your core logic with my one.
Happy Coding 😀
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject: Codable {
let quizzes: [Quiz]?
let pageno: Int?
let nextURL: String?
enum CodingKeys: String, CodingKey {
case quizzes, pageno
case nextURL = "nextUrl"
}
}
struct Quiz: Codable {
let id: Int?
let question: String?
let author: Author?
let attachment: Attachment?
let favourite: Bool?
let tips: [String]?
}
struct Attachment: Codable {
let filename: String?
let mime: MIME?
let url: String?
}
enum MIME: String, Codable {
case imageJPEG = "image/jpeg"
}
struct Author: Codable {
let id: Int?
let isAdmin: Bool?
let username: String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Quiz")
self.tableView.dataSource = self
self.tableView.delegate = self
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
print("in prepare images")
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
for i in 0...self.totalQuizzes.count-1 {
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
let imageData:NSData = NSData(contentsOf: imageUrl)!
let image = UIImage(data: imageData as Data)
print("hola (i)")
self.quizzesImages.append(image!)
print(self.quizzesImages.count)
// When from background thread, UI needs to be updated on main_queue
}
DispatchQueue.main.async {
print(self.quizzesImages.count)
self.tableView.reloadData()
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
print("num of rows (totalQuizzes.count)")
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("in cellForRowAt (indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz")!
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.textLabel?.text = "(quiz.author?.username) (quiz.question)"
cell.imageView?.image = images
return cell
}}
This worked, I had toself.tableView.reloadData()
onprepareImages
. Thank you very much
– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
add a comment |
See this screen shot form my playground
I tried to run your code in playground and managed to get it work with some changes please see the following.
Note
To make it run in playground i have to make some assumptions just replace your core logic with my one.
Happy Coding 😀
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject: Codable {
let quizzes: [Quiz]?
let pageno: Int?
let nextURL: String?
enum CodingKeys: String, CodingKey {
case quizzes, pageno
case nextURL = "nextUrl"
}
}
struct Quiz: Codable {
let id: Int?
let question: String?
let author: Author?
let attachment: Attachment?
let favourite: Bool?
let tips: [String]?
}
struct Attachment: Codable {
let filename: String?
let mime: MIME?
let url: String?
}
enum MIME: String, Codable {
case imageJPEG = "image/jpeg"
}
struct Author: Codable {
let id: Int?
let isAdmin: Bool?
let username: String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Quiz")
self.tableView.dataSource = self
self.tableView.delegate = self
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
print("in prepare images")
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
for i in 0...self.totalQuizzes.count-1 {
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
let imageData:NSData = NSData(contentsOf: imageUrl)!
let image = UIImage(data: imageData as Data)
print("hola (i)")
self.quizzesImages.append(image!)
print(self.quizzesImages.count)
// When from background thread, UI needs to be updated on main_queue
}
DispatchQueue.main.async {
print(self.quizzesImages.count)
self.tableView.reloadData()
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
print("num of rows (totalQuizzes.count)")
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("in cellForRowAt (indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz")!
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.textLabel?.text = "(quiz.author?.username) (quiz.question)"
cell.imageView?.image = images
return cell
}}
See this screen shot form my playground
I tried to run your code in playground and managed to get it work with some changes please see the following.
Note
To make it run in playground i have to make some assumptions just replace your core logic with my one.
Happy Coding 😀
import UIKit
// Estructura del JSON que devuelve la URL
struct ResponseObject: Codable {
let quizzes: [Quiz]?
let pageno: Int?
let nextURL: String?
enum CodingKeys: String, CodingKey {
case quizzes, pageno
case nextURL = "nextUrl"
}
}
struct Quiz: Codable {
let id: Int?
let question: String?
let author: Author?
let attachment: Attachment?
let favourite: Bool?
let tips: [String]?
}
struct Attachment: Codable {
let filename: String?
let mime: MIME?
let url: String?
}
enum MIME: String, Codable {
case imageJPEG = "image/jpeg"
}
struct Author: Codable {
let id: Int?
let isAdmin: Bool?
let username: String?
}
class QuizzesTableViewController: UITableViewController {
// Aquí se guardan los quizzes cargados de la URL
var totalQuizzes = [Quiz]()
var quizzesImages = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 90.0
navigationController?.navigationBar.prefersLargeTitles = true
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Quiz")
self.tableView.dataSource = self
self.tableView.delegate = self
downloadQuizzes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func prepareImages(){
print("in prepare images")
// Start background thread so that image loading does not make app unresponsive
DispatchQueue.global(qos: .userInitiated).async {
for i in 0...self.totalQuizzes.count-1 {
let imageUrlString = self.totalQuizzes[i].attachment?.url
let imageUrl:URL = URL(string: imageUrlString!)!
print(imageUrl)
let imageData:NSData = NSData(contentsOf: imageUrl)!
let image = UIImage(data: imageData as Data)
print("hola (i)")
self.quizzesImages.append(image!)
print(self.quizzesImages.count)
// When from background thread, UI needs to be updated on main_queue
}
DispatchQueue.main.async {
print(self.quizzesImages.count)
self.tableView.reloadData()
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func downloadQuizzes(){
let QUIZZES_URL = "https://quiz2019.herokuapp.com/api/quizzes?token=945d3bf7d4c709d69940"
if let url = URL(string: QUIZZES_URL){
let queue = DispatchQueue(label: "download quizzes queue")
queue.async {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
let data = try? Data(contentsOf: url, options: .alwaysMapped)
let decoder = JSONDecoder()
do{
let response = try decoder.decode(ResponseObject.self, from: data!)
DispatchQueue.main.async {
if (response.quizzes!.count != 0){
self.totalQuizzes.append(contentsOf: response.quizzes!)
self.prepareImages()
print(self.totalQuizzes.count)
}
}
}
catch {
print(error)
}
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
print("num of rows (totalQuizzes.count)")
return totalQuizzes.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("in cellForRowAt (indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "Quiz")!
let quiz = totalQuizzes[indexPath.row]
let images = quizzesImages[indexPath.row]
cell.textLabel?.text = "(quiz.author?.username) (quiz.question)"
cell.imageView?.image = images
return cell
}}
edited Nov 23 '18 at 17:35
answered Nov 23 '18 at 17:19
Harshal BhavsarHarshal Bhavsar
861931
861931
This worked, I had toself.tableView.reloadData()
onprepareImages
. Thank you very much
– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
add a comment |
This worked, I had toself.tableView.reloadData()
onprepareImages
. Thank you very much
– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
This worked, I had to
self.tableView.reloadData()
on prepareImages
. Thank you very much– martingoldthen
Nov 23 '18 at 17:47
This worked, I had to
self.tableView.reloadData()
on prepareImages
. Thank you very much– martingoldthen
Nov 23 '18 at 17:47
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Yes and that too after ending the for loop
– Harshal Bhavsar
Nov 23 '18 at 17:48
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
Feel free to upvote also if it helped. Once Again Happy coding
– Harshal Bhavsar
Nov 23 '18 at 17:49
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
I did, but my reputation is under 15 and it doesn't show, sorry
– martingoldthen
Nov 23 '18 at 17:53
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
No Worries Happy Coding. Keep Learning
– Harshal Bhavsar
Nov 23 '18 at 17:55
add a comment |
Since you didn't say what line the exception is happening on, my best guess is that it's happening on this line.
let images = quizzesImages[indexPath.row]
The issue is in downloadQuizzes
. In there you call prepareImages
then a couple lines later call reloadData
. Since prepareImages
does an async task, it isn't blocking downloadQuizzes
from finishing running. This causes reloadData
to be called before the async part of prepareImages
is finished.
You'll need to make sure prepareImages
is finished running before calling reloadData
.
Another option is to use a library like Kingfisher that will only download the images when they need to be displayed in a cell rather then downloading them all and slowing down showing the table.
Additional Note:
You shouldn't be using Data(contentsOf:)
to load remote content, URLSession
is the correct option for it.
Yes! Taking out all the async tasks inprepareImages
makes it work! How would I do it soreloadData
isn't called untilprepareImages
is done? Thank you so much!
– martingoldthen
Nov 23 '18 at 17:10
add a comment |
Since you didn't say what line the exception is happening on, my best guess is that it's happening on this line.
let images = quizzesImages[indexPath.row]
The issue is in downloadQuizzes
. In there you call prepareImages
then a couple lines later call reloadData
. Since prepareImages
does an async task, it isn't blocking downloadQuizzes
from finishing running. This causes reloadData
to be called before the async part of prepareImages
is finished.
You'll need to make sure prepareImages
is finished running before calling reloadData
.
Another option is to use a library like Kingfisher that will only download the images when they need to be displayed in a cell rather then downloading them all and slowing down showing the table.
Additional Note:
You shouldn't be using Data(contentsOf:)
to load remote content, URLSession
is the correct option for it.
Yes! Taking out all the async tasks inprepareImages
makes it work! How would I do it soreloadData
isn't called untilprepareImages
is done? Thank you so much!
– martingoldthen
Nov 23 '18 at 17:10
add a comment |
Since you didn't say what line the exception is happening on, my best guess is that it's happening on this line.
let images = quizzesImages[indexPath.row]
The issue is in downloadQuizzes
. In there you call prepareImages
then a couple lines later call reloadData
. Since prepareImages
does an async task, it isn't blocking downloadQuizzes
from finishing running. This causes reloadData
to be called before the async part of prepareImages
is finished.
You'll need to make sure prepareImages
is finished running before calling reloadData
.
Another option is to use a library like Kingfisher that will only download the images when they need to be displayed in a cell rather then downloading them all and slowing down showing the table.
Additional Note:
You shouldn't be using Data(contentsOf:)
to load remote content, URLSession
is the correct option for it.
Since you didn't say what line the exception is happening on, my best guess is that it's happening on this line.
let images = quizzesImages[indexPath.row]
The issue is in downloadQuizzes
. In there you call prepareImages
then a couple lines later call reloadData
. Since prepareImages
does an async task, it isn't blocking downloadQuizzes
from finishing running. This causes reloadData
to be called before the async part of prepareImages
is finished.
You'll need to make sure prepareImages
is finished running before calling reloadData
.
Another option is to use a library like Kingfisher that will only download the images when they need to be displayed in a cell rather then downloading them all and slowing down showing the table.
Additional Note:
You shouldn't be using Data(contentsOf:)
to load remote content, URLSession
is the correct option for it.
answered Nov 23 '18 at 17:02
Craig SiemensCraig Siemens
9,54612042
9,54612042
Yes! Taking out all the async tasks inprepareImages
makes it work! How would I do it soreloadData
isn't called untilprepareImages
is done? Thank you so much!
– martingoldthen
Nov 23 '18 at 17:10
add a comment |
Yes! Taking out all the async tasks inprepareImages
makes it work! How would I do it soreloadData
isn't called untilprepareImages
is done? Thank you so much!
– martingoldthen
Nov 23 '18 at 17:10
Yes! Taking out all the async tasks in
prepareImages
makes it work! How would I do it so reloadData
isn't called until prepareImages
is done? Thank you so much!– martingoldthen
Nov 23 '18 at 17:10
Yes! Taking out all the async tasks in
prepareImages
makes it work! How would I do it so reloadData
isn't called until prepareImages
is done? Thank you so much!– martingoldthen
Nov 23 '18 at 17:10
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53450085%2findex-out-of-range-exception-using-dispatchqueue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
You check if
esponse.quizzes!.count != 0
is true? Try printresponse.quizzes
– Augusto
Nov 23 '18 at 16:40
@Augusto yes, it is, totalQuizzes has 10 elements after running so the code below gets executed
– martingoldthen
Nov 23 '18 at 16:49
@martingoldthen can you give what is inside Quiz
– Harshal Bhavsar
Nov 23 '18 at 16:50
@martingoldthen give the entity class Defination of Quiz so can run and see it
– Harshal Bhavsar
Nov 23 '18 at 16:53
1
@HarshalBhavsar This is Quiz.swift file
import Foundation struct Quiz : Codable { let id : Int? let question : String? let author : Author? let attachment : Attachment? let favourite : Bool? let tips : [String]? struct Author: Codable { let id: Int? let isAdmin : Bool? let username : String? } struct Attachment : Codable { let filename : String? let mime : String? let url : String? } }
– martingoldthen
Nov 23 '18 at 16:53