Закрытие приложения MACOS никогда не выполнялось

Я быстро создал консольное приложение для macOS, но код никогда не выполняется, = мне нужно использовать семафор, но есть ли другой способ сделать это? моя цель - создать метод, возвращающий файл json

class test{
    func gizlo(){
        let config = URLSessionConfiguration.default // Session Configuration
        let session = URLSession(configuration: config) // Load configuration into Session
        let url = URL(string: "https://itunes.apple.com/fr/rss/topmovies/limit=25/json")!

        let task = session.dataTask(with: url, completionHandler: {
            (data, response, error) in

            if error != nil {

                print(error!.localizedDescription)

            } else {

                do {

                    if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
                    {
                        print(json)
                    }

                } catch {

                    print("error in JSONSerialization")

                }


            }

        })

        task.resume()
    }
}

let tr=test()
tr.gizlo()

Спасибо


person David Tavan    schedule 20.04.2017    source источник
comment
Вы можете добавить RunLoop.main.run () в и файла. Но использование семафора предпочтительнее, главное не допустить закрытия консолидации.   -  person Oleg Gordiichuk    schedule 20.04.2017
comment
Связанные (дубликаты?): CFRunLoop в программе командной строки Swift   -  person Martin R    schedule 20.04.2017


Ответы (2)


Чтобы избежать семафоров, вы можете использовать простой readLine(), который будет ждать ввода с клавиатуры. Да, это не очевидно, но это работает, потому что предотвращает выход из терминального приложения.

Просто добавьте в и файла:

_ = readLine()
person Oleg Gordiichuk    schedule 20.04.2017

Как указывает Олег, размещение readLine() в конце кода верхнего уровня предотвратит завершение программы до тех пор, пока вы не нажмете Enter в терминале или там, где указывает FileHandle.standardInput. Это, вероятно, подходит для быстрого тестирования кода в отладчике или на игровой площадке. Бесконечный цикл также будет работать, хотя вам придется фактически завершить его в отладчике или с помощью kill из командной строки.

Настоящая проблема в том, почему вы не хотите использовать семафор. Поскольку их нетрудно использовать, я рискну предположить, что это просто потому, что вы не хотите загрязнять свой обработчик завершения задачи асинхронных данных семафором, когда вам, вероятно, нужно только дождаться данных для тестирования. целей.

Если предположить, что моя догадка верна, то на самом деле проблема заключается не в использовании семафора, а в том, где, по вашему мнению, вам нужно их поместить. Как однажды сказал Дэвид Уиллер: «Любую проблему можно решить, добавив уровень косвенности.

Вы не хотите, чтобы семафор явно был в обработчике завершения, который вы передаете dataTask. Таким образом, одним из решений было бы заставить gizlo принимать собственный обработчик завершения, а затем создать метод, который вызывает gizlo с замыканием, обрабатывающим семафор. Таким образом, вы можете разделить их и даже добавить гибкости для других целей. Я изменил ваш код для этого:

import Foundation
import Dispatch // <-- Added - using DispatchSemaphore

class test{
    func gizlo(_ completion: ((Result<[String: Any]?, Error>) -> Void)? = nil) { // <-- Added externally provided completion handler
        let config = URLSessionConfiguration.default // Session Configuration
        let session = URLSession(configuration: config) // Load configuration into Session
        let url = URL(string: "https://itunes.apple.com/fr/rss/topmovies/limit=25/json")!

        let task = session.dataTask(with: url, completionHandler: {
            (data, response, error) in

            let result: Result<[String: Any]?, Error>
            if let responseError = error { // <-- Changed to optional binding

                print(responseError.localizedDescription)
                result = .failure(responseError) // <-- Added this

            } else {

                do {

                    if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
                    {
                        print(json)
                        result = .success(json) // <-- Added this
                    }
                    else { // <-- Added this else block
                        result = .success(nil)
                    }
                } catch {

                    print("error in JSONSerialization")
                    result = .failure(error) // <-- Added this
                }

            }

            completion?(result)  // <-- Added this call
        })

        task.resume()
    }

    func blockingGizlo() throws -> [String: Any]? // <-- Added this method
    {
        let sem = DispatchSemaphore(value: 1)
        sem.wait()
        var result: Result<[String: Any]?, Error>? = nil
        gizlo {
            result = $0
            sem.signal()
        }
        sem.wait() // This wait will block until the closure calls signal
        sem.signal() // Release the second wait.

        switch result
        {
            case .success(let json)  : return json
            case .failure(let error) : throw error
            case .none: fatalError("Unreachable")
        }
    }
}

let tr=test()

do {
    let json = try tr.blockingGizlo()
    print("\(json?.description ?? "nil")")
}
catch { print("Error: \(error.localizedDescription)") }
person Chip Jarred    schedule 26.02.2021