0

I am making a command line tool in Xcode. The tool reads urls from a JSON file and then it should loop through each URL and check to see if the urls return a 200 HTTP code. I would like each url to run and then when each url check is done, move to the next one. My current code is as follows:

Services.shared.readJsonFile { file in

    if file == nil {
        print("File does not exist!")
        print(FileManager.default.currentDirectoryPath)
        exit(EXIT_SUCCESS)
    }

    let dispatchGroup = DispatchGroup()
    let dispatchQueue = DispatchQueue(label: "taskQueue")
    let dispatchSemaphore = DispatchSemaphore(value: 0)

    dispatchQueue.async {

        for servers in (file?.monitors)! {

            let urlString = servers.url

           print("1")

            dispatchGroup.enter()

            Services.shared.checkConnection(url: urlString, id: servers.component_id) { conresult in

                 print("2")

                if conresult == .down {

                    print("\(urlString) is DOWN!")

                } else {

                    print("\(urlString) is UP!")

                }

                dispatchSemaphore.signal()
                dispatchGroup.leave()

            }

            dispatchSemaphore.wait()
        }
    }


        dispatchGroup.notify(queue: dispatchQueue) {

            exit(EXIT_SUCCESS)
        }

}

dispatchMain()

I added a print 1 and print 2 to see the order in which it is being printed and for some reason the output is as follows:

1
2
https://google.com is UP!
1
2
https://esg3g2sdg32.com is DOWN!
2
https://esg3g2sdg32.com is DOWN!
Illegal instruction: 4

I only have two urls in the file but it always runs the second url twice and it looks like it prints out "2" twice at the end without going back to "1".

UPDATE: Removed semaphores as follows:

Services.shared.readJsonFile { file in

    if file == nil {
        print("File does not exist!")
        print(FileManager.default.currentDirectoryPath)
        exit(EXIT_SUCCESS)
    }

    let dispatchGroup = DispatchGroup()



        for servers in (file?.monitors)! {

            dispatchGroup.enter()

            let urlString = servers.url

           print("1")



            Services.shared.checkConnection(url: urlString, id: servers.component_id) { conresult in

                 print("2")

                if conresult == .down {

                    print("\(urlString) is DOWN!")

                } else {

                    print("\(urlString) is UP!")

                }


                dispatchGroup.leave()

            }

        }



        dispatchGroup.notify(queue: .main) {

            exit(EXIT_SUCCESS)
        }

}

dispatchMain()

and now my output is this:

1
1
2
https://esg3g2sdg32.com is DOWN!
2
https://esg3g2sdg32.com is DOWN!
logout
Nick
  • 228
  • 6
  • 20
  • 1
    Do not use semaphores. Remove the semaphore stuff entirely; it's messing up your code. – matt Jul 23 '18 at 14:17
  • How do I have each loop wait until previous completes without using semaphores? I tried just using dispatch group but that didn't work either. – Nick Jul 23 '18 at 14:18
  • You do not "wait". Just use DispatchGroup correctly — but here there probably isn't any need for that either. It seems to me that your _real_ problem is merely that the command line tool exits before any async code can run. But semaphores and dispatch groups are not the solution to that. – matt Jul 23 '18 at 14:19
  • 1
    You need a runloop to keep the command-line tool alive. – matt Jul 23 '18 at 14:21
  • By adding `dispatchMain()` at the end that will prevent the command line tool from exiting until I call exit. I updated the question with new code after removing the semaphores and output looks each loop is being run without waiting. – Nick Jul 23 '18 at 14:26
  • Remove the dispatch group too. It isn't getting you anything. You don't care what order things run in, and you don't need to wait until one check is finished before doing the next. What you need to know is why you're seeing the same URL twice, and your logging is not getting at that. – matt Jul 23 '18 at 14:34
  • I thought I was getting the same url twice because it was rushing through the loop without waiting, so it was checking the same url twice while the asyc code from the first loop was being run in background. – Nick Jul 23 '18 at 14:39
  • And the dispatch group is there to hold the program open until all the loops complete and then I can close the app with `dispatchGroup.notify` – Nick Jul 23 '18 at 14:41
  • "I thought" Don't think. Debug! — And I already explained that the way to "hold the program open" is to run the runloop. You _still_ have not done that even though I showed you two links that explain it. – matt Jul 23 '18 at 15:02

0 Answers0