0

I am trying to access the value of "x" in nested loop but each time i try this the value of "x" in inner loop it gets varied.

var downloads_array = [[URL]]()//edited
func downloadImages(){

        var count = images.count
        let storage = Storage.storage().reference()

        for x in 0...count-1{
            var anime = [String]()
            anime.append(images[x])
            anime.append(images[x] + "1")
            print("outside the second loop x is : \(x)")

            for i in anime{
                let storageRef = storage.child("images/\(i).jpg")
                storageRef.downloadURL { (url, error) in
                    if let error = error{
                        print(error.localizedDescription)
                    }
                    else{
                        print(x)
                        self.downloads_array[x].append(url!)//edited
                    }
                }
            }
        }

    }

The ouput is:

outside the second loop x is : 0
outside the second loop x is : 1
outside the second loop x is : 2
outside the second loop x is : 3
outside the second loop x is : 4
outside the second loop x is : 5
0
3
0
1
1
4
2
5
3
4
2
5

I am new to swift development please guide me in solving this issue.

3
  • Hi Sathis Kumar, Can you please specify what actually should be the response/result you are looking for your code. Commented Sep 17, 2018 at 6:40
  • Hello bro, I have an array of type [[URL]](), i want to append the download url of the loop based on the value of x Commented Sep 17, 2018 at 6:43
  • for the correct answer you need to provide the sample data to me, like downloads_array value, images value and what is the output you are looking for. Commented Sep 17, 2018 at 6:59

4 Answers 4

2

Your storageRef.downloadURL is an async call, which means it will take time for the completion block to be executed. The for loop would be executed and count * 2 calls would be hit. Depending on how fast each response is received the appropriate completion is called resulting in the order that you are getting.

func downloadImages(){
    var count = images.count
    let storage = Storage.storage().reference()

    for x in 0...count-1{
        var anime = [String]()
        anime.append(images[x])
        anime.append(images[x] + "1")
        print("outside the second loop x is : \(x)")

        print(x) // printing it here will give you the order as is
        for i in anime {
            let storageRef = storage.child("images/\(i).jpg")
            storageRef.downloadURL { (url, error) in
                if let error = error{
                    print(error.localizedDescription)
                }
                else{
                    print(x)
                }
            }
        }
    }
}

Since you do not have control over the order in which the completion block is executed. A dictionary would be one solution to your problem. Store the index as the key and url array as the value. Or you could have a struct which stores the urls for the corresponding index and sort it.

Sign up to request clarification or add additional context in comments.

9 Comments

How to make it synchronous bro? can you explain me or please guide me how to learn about synchronous and asynchronous
@sathishkumar Network calls are asynchronous by nature. If you want to make them synchronous, you should hit the network call only after you have received the previous one. Then you would need to restructure your code to hit network calls from your completion.
at the place where you asked me to print "x" i created a variable and assigned like let y = x but the values are still random(like 00,11,32,23,44,55). I want those numbers to append the url values to the array. How to do that?
@sathishkumar that was my bad. Edited it.
@sathishkumar a possible solution i can think of is using a dictionary to store the urls with index as the key and url array as the value.
|
2

storageRef.downloadURL is async so the code will continue executing and x value will change. The solution here is to capture the current x value either through an intermediary variable or though block capture

Block capture

var downloads_array = [[URL]]()//edited
func downloadImages(){

    var count = images.count
    let storage = Storage.storage().reference()

    for x in 0...count-1{
        var anime = [String]()
        anime.append(images[x])
        anime.append(images[x] + "1")
        print("outside the second loop x is : \(x)")

        for i in anime{
            let storageRef = storage.child("images/\(i).jpg")
            storageRef.downloadURL { [x] (url, error) in // block capture
                if let error = error{
                    print(error.localizedDescription)
                }
                else{
                    print(x)
                    self.downloads_array[x].append(url!)//edited
                }
            }
        }
    }

}

 -

Intermediary variable

var downloads_array = [[URL]]()//edited
func downloadImages(){

    var count = images.count
    let storage = Storage.storage().reference()

    for x in 0...count-1{
        var anime = [String]()
        anime.append(images[x])
        anime.append(images[x] + "1")
        print("outside the second loop x is : \(x)")

        for i in anime{
            let storageRef = storage.child("images/\(i).jpg")
            let currentX = x // intermediary variable
            storageRef.downloadURL { (url, error) in
                if let error = error{
                    print(error.localizedDescription)
                }
                else{
                    print(currentX)
                    self.downloads_array[currentX].append(url!)//edited
                }
            }
        }
    }

}

9 Comments

Hello @Francescu, even after using block capture as you mentioned those values of x are getting displayed very random like(301041432255)
@sathishkumar Really strange, try with the second solution and tell me if you still have the bug
@Francescu this time the output is (303421012455)
yeah i tried both intermediate variables and block capture everytime, the value of x is randomised
I suspect a debugger issue, but the code should work fine. Is the code crashing?
|
1

Not sure exactly what you need but I think you're trying to implement something like this : -

func downloadImages(){
    var count = images.count
    let storage = Storage.storage().reference()
    var data : [String:Int] = []
    for x in 0...count-1{
        var anime = [String]()
        anime.append(images[x])
        anime.append(images[x] + "1")
        print("outside the second loop x is : \(x)")

        for i in anime {
            let storageRef = storage.child("images/\(i).jpg")
            data["YourUrl"] = x // Replace YourUrl with your url string
            storageRef.downloadURL { (url, error) in
                if let error = error{
                    print(error.localizedDescription)
                }
                else{
                    if let value = data[url.absoluteString]{
                        print(value)
                    }

                }
            }
        }
    }
}

7 Comments

hello bro, thanks for effort. My logic is there is an array named downloaded_images = [[URL]](), when there is an image present with the name(i), I want to append that url like[ [url_image1,url_image2],[..,...]]. for that I need the integer values of "x" in order.
did you try my code? just replace data["YourUrl"] with your url address and check the value of data in the end of the loop you'll the url and its index as the value try that @sathishkumar
and i don't know the url is URL or String in your case so you have to take care of the thing that you will need to add url String into the data dictionary and retrieve String to compare
atleast have the courtesy to reply where others have invested there time too @sathishkumar
Yeah extremely sorry bro. Kinda stuck here Thank you so much
|
0

As the Firebase Storage was an Asynchronous call(network call), We can't retain the value as the order will be non-sequential. So i Created a dictionary with String and URL to store the respective download URL for the image

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.