Подскажите как решить Unexpected non-void return value in void function

swift

#1

Всем добрый день! Имею такую функцию из нее мне нужно вернуть полученное значение из dataToken
Получаю ошибку Unexpected non-void return value in void function. Понимаю что dataTask не возвращает значение.Подскажите как это обойти
Спасибо!
Всем хорошего дня!

func dataToken ( ) -> String {

    let urlString = "http://хх.хх.хх.хх/api/v2/getToken/?type=base&ais="+getToken()
    let url = URL(string: urlString)

    URLSession.shared.dataTask(with: url!) { (data, response, error) in
        //guard let data = data else {return}

        do {
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
            
            guard  let dataToken = json["data"] as? String else {return}
            
            return dataToken
        
            
        } catch {
            print (error)
            
        }
        
    }.resume()

}

#2

Попробуй так

func dataToken() -> String {
    var token = String()
    let urlString = "http://хх.хх.хх.хх/api/v2/getToken/?type=base&ais=" + getToken()
    let url = URL(string: urlString)

    URLSession.shared.dataTask(with: url!) { (data, _, _) in


        do {
            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]

            guard let dataToken = json["data"] as? String else {return}

            token = dataToken


        } catch {
            print (error)

        }

        }.resume()

    return token
}

#3

Спасибо, Psilc. Переменную объявлял не в том месте метода )


#4

Ошибки нет но и результат тоже возвращает пустой (


#5

Где гарантия, что токен получит значение из асинхронного замыкания для сетевого запроса ДО того, как будет возвращен из функции?

Если нужна функция для получения чего-то по сети в том виде, как хотите Вы, делайте синхронный запрос.

Но корректнее задача решается, передачей в исходную функцию хендлера, что и получит Вашу строку из сети и Вы с ней что-то сможете делать.


#6

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


#7

Как вариант создайте глобальный объект. По виду это похоже на что-то типо AuthService. Можно сделать под синглтон. Тогда не понадобится дополнительное замыкание.


#8

Проще токен записывать в SharedPreferences. Таким образом он будет доступен везде и всегда, пока юзер не удалит приложение или не выйдет из него (само собой нужно реализовать логику удаления при этом).


#9

Получить токен при запуске приложения дешевле как кажется, чем операции сохранении и проверки валидности.


#10

Любой http запрос уже не может быть дешевле, учитывая что все http запросы на iOS выполняются дольше, чем на Андроиде.
Но опять же, все зависит от требований к приложению. Если при запуске нужен всегда свежий и валидный токен, то придется запрашивать каждый раз. Если нет, то при любом запросе придет 401, после которой нужно обновить токен и повторить предыдущий запрос.


#11

Для моего приложения всегда нужен свежий токен. Как же мне это правильно реализовать?


#12

Это уже зависит от ваших требований: как часто токен может меняться, в каком случае вам нужно его обновлять.
Самый простой вариант, запрашивать новый токен при открытии приложения. Но опять же, если приложение не закрывалось к примеру пару дней, после чего юзер разворачивает его, что в этом случае вам нужно?


#13

Токен обновляется при открытии приложения и при разворачивании если оно не было закрыто


#14

Для одного случая подойдет метод из Application.switf. Там будет что-то вроде didBecomeActive или didForeground.
Хотя наверное это подойдет для обеих случаев. Нужно проверять.
Еще один из способов, при запуске приложения, запрашивать новый токен в главном ViewController’e, который стартует в начале.
Для очень продвинутого способа можно использовать RxSwift.


#15

Приложение генерирует токен - это токен передается в запросы для получения одноразового токена. который передается в запрос для получения данных с сервера в виде json. На подобие мобильного приложения (Киноафиша)
Извиняюсь, если коряво написал.)


#16

Уважаемый

RexHunt
То что вы порекомендовали в последнем посте применимо к моему приложению?


#17

Да, применимо.
Попробуйте через этот метод
applicationDidBecomeActive(_ application: UIApplication)
в AppDelegate

Вот как это реализовано у нас в приложении

func applicationDidBecomeActive(_ application: UIApplication) {
    performSelector(inBackground: #selector(checkIsAppVersionSupported), with: application)
}

@objc private func checkIsAppVersionSupported(_ application: UIApplication) {
        if let url = URL(string: "url"),
            let appVer = application.applicationVersion,
            let appBuild = application.applicationBuild {
            do {
                let jsonData = try Data(contentsOf: url)
                let jsonObj = try JSONSerialization.jsonObject(with: jsonData, options: [])
                if let dictionary = jsonObj as? [String: Any],
                    let versions = dictionary["supported_version_ios"] as? [String] {
                    
                    if !versions.contains(appVer) {
                        NotificationCenter.default.post(name: Account.notificationAppNotSupported,
                                                        object: nil)
                    }
                }
            } catch {
                // ignore error
            }
        }
    }

#18

RexHunt
Спасибо!
Буду пробовать!