Celine
Celine

Reputation: 29

iOS 14 StoreKit - SKCloudServiceController's requestusertoken not being called properly

I am trying to play songs on iOS 14 using Apple Music API. I have the developer's token, and I have asked for the permission for accessing the user's apple music.

However, when I call requestusertoken api, its closure never gets called, so obviously I don't receive anything from the request - not even an error. It's driving me crazy.

Here is my code. What am I doing wrong?

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 }

Upvotes: 2

Views: 666

Answers (4)

Jack Vanderpump
Jack Vanderpump

Reputation: 486

I think we've all got stuck on the same tutorial. To fix, I put it on a different thread as the lock was holding up the main thread hence preventing the completion handler.

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

If it's the same tutorial, this will put the fetchStorefrontID() and the getUserToken() methods (which is called by the former) on a background thread and allow the completion handlers and the lock.signal() to occur.

If it's not, then this shall suffice for an answer:

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

Upvotes: 2

Hohyeon Moon
Hohyeon Moon

Reputation: 36

I've tried the code and there were two major problems.

First, DispatchSemaphore makes the return line execute too early. Second, original developer token doesn't work due to latest iOS 14.3 issue.

So, I first erased 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)
        }
    }
}

Then tweaked developer token following this repository.

Now, it's printing user token properly. I hope this helped.

Upvotes: 2

serenn
serenn

Reputation: 1828

Okay so I know what's going on -- the DispatchSemaphore is being locked right after it's being created -- so it's never executing that code. Once I made the Semaphore value 1 instead of 0 it started to execute -- but then I had issues with the rest of the code because of the sequencing of events.

It looks like perhaps you're working with the same tutorial I was working through on Apple Music SDK integration -- if that's the case, I basically tweaked the code to :

  1. download the user token to a local variable, and then the other methods begin to reference it in their requests.
  2. Remove the Semaphore lock in the getuserToken() method only
  3. The rest started working again, without having to change any other DispatchSemaphore values.

By no means am I an expert in how DispatchSemaphore works and best practices with apple music user tokens, but wanted to at least let you know why you were running into the same wall as me -- with no code being executed at all.

Upvotes: 1

Nick Sorge
Nick Sorge

Reputation: 21

Did you remove Bearer from your developerToken?

Upvotes: 1

Related Questions