iOS 14 StoreKit — неправильно вызывается requestusertoken SKCloudServiceController

#ios #swift #authentication #storekit #apple-musickit

#iOS #swift #аутентификация #storekit #apple-musickit

Вопрос:

Я пытаюсь воспроизводить песни на iOS 14 с помощью Apple Music API. У меня есть токен разработчика, и я запросил разрешение на доступ к Apple Music пользователя.

Однако, когда я вызываю api requestusertoken, его закрытие никогда не вызывается, поэтому, очевидно, я ничего не получаю от запроса — даже ошибки. Это сводит меня с ума.

Вот мой код. Что я делаю не так?

 func getUserToken() -> String {
var userToken = String()

let lock = DispatchSemaphore(value: 0)

SKCloudServiceController().requestUserToken(forDeveloperToken: developerToken) { (receivedToken, error) in
    guard error == nil else { return }
    if let token = receivedToken {
        userToken = token
        lock.signal()
    }
}

lock.wait()
return userToken }
  

Комментарии:

1. Точно такая же проблема.. Вы когда-нибудь это понимали?

Ответ №1:

Я попробовал код, и возникли две основные проблемы.

Во-первых, DispatchSemaphore заставляет строку возврата выполняться слишком рано. Во-вторых, исходный токен разработчика не работает из-за последней проблемы iOS 14.3.

Итак, я сначала удалил DispatchSemaphore.

 func getUserToken() {
    var userToken = String()
    
    SKCloudServiceController().requestUserToken(forDeveloperToken: developerToken) { (receivedToken, error) in
        guard error == nil else { return }
        
        if let token = receivedToken {
            userToken = token
            print(userToken)
        }
    }
}
  

Затем изменен токен разработчика, следующий за этим репозиторием.

Теперь он правильно печатает токен пользователя. Надеюсь, это помогло.

Ответ №2:

Я думаю, мы все застряли на одном и том же руководстве. Чтобы исправить, я поместил его в другой поток, поскольку блокировка задерживала основной поток, следовательно, предотвращая обработчик завершения.

 DispatchQueue.global(qos: .background).async {
   print(AppleMusicAPI().fetchStorefrontID())
}
  

Если это тот же учебник, это поместит методы fetchStorefrontID() и getUserToken() (который вызывается первым) в фоновый поток и позволит выполнить обработчики завершения и lock.signal() .

Если это не так, этого должно быть достаточно для ответа:

 DispatchQueue.global(qos: .background).async {
   getUserToken()
}
  

Ответ №3:

Вы удалили Bearer из своего developerToken ?

Комментарии:

1. Привет, Ник, да, мой токен разработчика выглядит примерно так: пусть developerToken = «e *****.e *****.d ****A»

2. ОК. Потому что я не вижу остальной части вашего кода или класса / структуры. Возможно, у вас проблема со ссылкой. Если ваш класс / структура инициализируется в func без наличия глобальной переменной, ваш объект будет освобожден, и блок завершения никогда не вызывается.

3. БОЖЕ МОЙ! Это было для меня… Я добавлял «Bearer» к своему токену разработчика при подготовке к вызову api.music.apple.com . Ого!

Ответ №4:

Хорошо, я знаю, что происходит — DispatchSemaphore он блокируется сразу после его создания, поэтому он никогда не выполняет этот код. Однажды я ввел значение семафора 1 вместо 0 того, чтобы оно начало выполняться, но затем у меня возникли проблемы с остальной частью кода из-за последовательности событий.

Похоже, возможно, вы работаете с тем же учебным пособием, над которым я работал над интеграцией Apple Music SDK — если это так, я в основном изменил код, чтобы :

  1. загрузите токен пользователя в локальную переменную, а затем другие методы начнут ссылаться на него в своих запросах.
  2. Удалите блокировку семафора getuserToken() только в методе
  3. Остальные снова начали работать, без необходимости изменять какие-либо другие DispatchSemaphore значения.

Я ни в коем случае не являюсь экспертом в том, как работает DispatchSemaphore и как использовать лучшие практики с пользовательскими токенами Apple music, но хотел хотя бы сообщить вам, почему вы столкнулись с той же стеной, что и я — без выполнения кода вообще.