Austin
Austin

Reputation: 345

Logic Behind when a Function is Called in Objective-C

I am having a hard time as a beginner to Objective-C with learning how and when a function is being called, as I am not seeing it explicitly stated. Below is some code for logging into, and playing a song from the Spotify SDK that I found online.

#import "AppDelegate.h"

@interface AppDelegate ()
@property (nonatomic, strong) SPTAuth *auth;
@property (nonatomic, strong) SPTAudioStreamingController *player;
@property (nonatomic, strong) UIViewController *authViewController;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.auth = [SPTAuth defaultInstance];
    self.player = [SPTAudioStreamingController sharedInstance];

    // The client ID you got from the developer site
    self.auth.clientID = @"5bd669abf2a14fb59839c2c0570843fe";
    // The redirect URL as you entered it at the developer site
    self.auth.redirectURL = [NSURL URLWithString:@"spotlightmusic://returnafterlogin"];
    // Setting the `sessionUserDefaultsKey` enables SPTAuth to automatically store the session object for future use.
    self.auth.sessionUserDefaultsKey = @"current session";
    // Set the scopes you need the user to authorize. `SPTAuthStreamingScope` is required for playing audio.
    self.auth.requestedScopes = @[SPTAuthStreamingScope];

    // Become the streaming controller delegate
    self.player.delegate = self;

    // Start up the streaming controller.
    NSError *audioStreamingInitError;
    NSAssert([self.player startWithClientId:self.auth.clientID error:&audioStreamingInitError],
             @"There was a problem starting the Spotify SDK: %@", audioStreamingInitError.description);

    // Start authenticating when the app is finished launching
    dispatch_async(dispatch_get_main_queue(), ^{
        [self startAuthenticationFlow];
    });

    return YES;
}

- (void)startAuthenticationFlow
{
    // Check if we could use the access token we already have
    if ([self.auth.session isValid]) {
        // Use it to log in
        [self.player loginWithAccessToken:self.auth.session.accessToken];
    } else {
        // Get the URL to the Spotify authorization portal
        NSURL *authURL = [self.auth spotifyWebAuthenticationURL];
        // Present in a SafariViewController
        self.authViewController = [[SFSafariViewController alloc] initWithURL:authURL];
        [self.window.rootViewController presentViewController:self.authViewController animated:YES completion:nil];
    }
}

- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary *)options
{
    // If the incoming url is what we expect we handle it
    if ([self.auth canHandleURL:url]) {
        // Close the authentication window
        [self.authViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
        self.authViewController = nil;
        // Parse the incoming url to a session object
        [self.auth handleAuthCallbackWithTriggeredAuthURL:url callback:^(NSError *error, SPTSession *session) {
            if (session) {
                // login to the player
                [self.player loginWithAccessToken:self.auth.session.accessToken];
            }
        }];
        return YES;
    }
    return NO;
}

- (void)audioStreamingDidLogin:(SPTAudioStreamingController *)audioStreaming
{
    [self.player playSpotifyURI:@"spotify:track:3DWOTqMQGp5q75fnVsWwaN" startingWithIndex:0 startingWithPosition:0 callback:^(NSError *error) {
        if (error != nil) {
            NSLog(@"*** failed to play: %@", error);
            return;
        }
    }];
}

@end

I am wondering how exactly these functions are being called sequentially, and specifically how the audioStreamingDidLogin one is being run.

Additionally I was wondering how it would look to call that function from the view controller with some sort of input coming from the UI.

Any help with this logic would be greatly appreciated! Thanks.

Upvotes: 0

Views: 88

Answers (2)

CRD
CRD

Reputation: 53010

Your question is closely tied to the Spotify framework being used. It is not a question of when Objective-C is executing something - the language has a standard sequential execution model - but how the framework is doing callbacks, e.g. audioStreamingDidLogin, to your code and utilising threads/GCD to do concurrent execution.

First you should read the Spotify framework documentation.

You can also place a breakpoint at the start of each method and then run under the debugger. When a breakpoint is hit check which thread has stopped and the stack trace. That should give you a good idea of execution flow and the concurrent threads being used.

HTH

Upvotes: 1

danh
danh

Reputation: 62686

UIApplicationDelegate method application:didFinishLaunchingWithOptions: is called first, followed by application:openURL:options:.

That first app delegate method sets self as the delegate for an AudioStreamingController. This is how audioStreamingDidLogin gets called. You're telling the streaming controller, "Tell me (self) when interesting things happen". (See the SPTAudioStreamingControllerDelegate docs for what else it might tell you about).

You probably wouldn't (shouldn't) call this function directly, especially if there's a chance that you might call it before auth is complete. Doing so would likely result in an error on the call to playSpotifyURI. If you're certain that the user is authenticated, then you don't need to call it. Just call what it calls: playSpotifyURI.

Upvotes: 0

Related Questions