spotify / ios-sdk

Spotify SDK for iOS
https://developer.spotify.com/documentation/ios/
654 stars 185 forks source link

SPTLoginSampleAppSwift: doesn't work with Storyboard-based App, sessionManager events never called #268

Open NRJMons opened 4 years ago

NRJMons commented 4 years ago

Dear all

I tried to set everything up for SPTLoginSampleAppSwift and ensure it works (with the server token swap and refresh) -> works nicely !

I am now trying to create a new project from scratch, minimalistic that uses the Storyboard with one view being the ViewController coming from the sample app above.

The application works, the first scene is presented as the ViewController, when I click Connect, it switches to Spotify app on the iPhone and confirms with a "V" that the authorisation is successful (white V with a circle around it) and switches back to my App.

BUT, the interface with the cover image and all doesn't appear, it remains on the Connect button and doesn't detect it's connected.

I placed breakpoints and it appears that none of the delegate methods of sessionManager are ever called. Another issue is that the delegate methods of ApplicationDelegate are NOT called because it uses Scenes and therefore uses SceneDelegate instead.

With the breakpoints I see that none of the important variables are actually initialised: playerAPI, accessToken etc... are nil

Here is what I have in SceneDelegate, trying to mimic what was in ApplicationDelegate in the sample code: The rest of the code of the sample project is unchanged:

func sceneDidBecomeActive(_ scene: UIScene) {
        if let _ = rootViewController?.appRemote.connectionParameters.accessToken {
            rootViewController?.appRemote.connect()
        }
}
func sceneWillResignActive(_ scene: UIScene) {
       if (rootViewController?.appRemote.isConnected == true ) {
            rootViewController?.appRemote.disconnect()
        }
}
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
           // The code hereunder has been changed from the original that was in application opener:
           // original: rootViewController.sessionManager.application(app, open: url, options: options)
            rootViewController?.sessionManager.application(UIApplication.shared, open: url, options: [:])
        }
}

I saw that actually DidBecomeActive and WillResignActive are also never called, although it's a standard project.

Honestly I'm lost, what would help is a version of the sample project with a storyboard so I can get started...and I'm sure that many others would be interested too.

Thanks in advance Nico

NRJMons commented 4 years ago

Oddly enough, it works now but I have to face another problem. The validation works and the delegate methods of sessionManager are called. But I had to change the code quite heavily. Now I get the playerState info correctly but when I try to update the label using the update method all access to visual elements returns "error while unwrapping optional value returns nil" Super strange. I added the label for the track name in the storyboard and configured the outlet but when I access the label, Ii get the error, see code hereunder:

@IBOutlet weak var imgCover: UIImageView!
@IBOutlet weak var btnPausePlay: UIButton!
@IBOutlet weak var lblTrack: UILabel!

func update(playerState: SPTAppRemotePlayerState) {
        if let formerURI = lastPlayerState?.track.uri {
            if formerURI != playerState.track.uri {
                fetchArtwork(for: playerState.track)
            }
        } else {
            fetchArtwork(for: playerState.track)
        }
        lastPlayerState = playerState
        //self.lblTrack.text = playerState.track.name
        if playerState.isPaused {
            btnPausePlay.setImage(UIImage(named: "play"), for: .normal)
        } else {
            btnPausePlay.setImage(UIImage(named: "pause"), for: .normal)
        }
    }

SpotifyTest[11721:3632073] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file /Users/nicolasbouillon/OneDrive/Development/SpotifyTest/SpotifyTest/ViewController.swift, line 129 the error is on self.lblTrack.text = ..... Even doing this returns the same error: self.lblTrack.text = "Test"

As you can see above, the outlet is configured properly.

NRJMons commented 4 years ago

Well, after investigation, it seems that the initialisation of my controller is called TWIICE...why, Ii don't know.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var window: UIWindow?
let rootViewController : ViewController = {
    return (UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(identifier: "ViewController") as? ViewController)!
}()

That means that I may be having 2 separate instances running of the same view controller. When I call self.lblTrack.text = "Test" in viewDidLoad, it works, outside that function, it returns the fatal error....

henriwoodcock-old commented 4 years ago

Hi @NRJMons ,

I am struggling to even get the demos to work. I can run the ruby token exchange and get the app to load up, but when I click on the button I get an error.

I‘ve checked the ruby token exchange and the local host can be accessed on safari?

Is there a step by step on what to change / do? I’m new to app development so I could be missing some quite basic.

Thanks

rolflocher commented 4 years ago

@NRJMons It sounds like your IBOutlet for the label is messed up, because the text attrib allows optional values. Not Spotify related. Although I'd love a reply to my many aging issues @Spotify