Connect the world of sound

iOS SDK

The SoundCloud platform provides an SDK for building mobile apps targeted for iOS or desktop apps for Mac OS X. Getting started with the iOS SDK is easy. In this tutorial we will walk you through building a simple iOS application. We'll explain and provide sample code for common use cases along the way.

Installing the iOS SDK

Before you can get started, you must first register and receive a client id and secret that uniquely identify your application. Head over to the registration page and give your app a descriptive name. Use sampleproject://oauth as the Redirect URI.

Once you've got a set of client credentials, go ahead and create a new project in Xcode. To keep things simple, we'll be building a Single View Application for the iPhone. Make sure to check "Use Automatic Reference Counting" if it is not already checked.

Create a new Xcode Project
Your Create Project dialog should look like this.

Install SDK and Dependencies

Once your project has been created, you'll need to install the SoundCloud SDK and a few dependencies. This tutorial assumes you are using Git for version control. If you are not, adjust the steps accordingly.

Change into your project directory and run the following commands from the terminal:

git submodule add git://github.com/soundcloud/CocoaSoundCloudAPI.git
git submodule add git://github.com/nxtbgthng/OAuth2Client.git
git submodule add git://github.com/nxtbgthng/JSONKit.git
git submodule add git://github.com/nxtbgthng/OHAttributedLabel.git
git submodule add git://github.com/soundcloud/CocoaSoundCloudUI.git

The first submodule is the SoundCloud iOS SDK. The rest are dependencies that make it easier to deal with things like OAuth, JSON, and various UI elements we'll use later on.

Now that the SDK and dependencies are checked out as submodules in your project directory, the next step is to add them to your Xcode project. Right click on your project name in the Project Navigator and select "Add Files to Project". When prompted, navigate to the CocoaSoundCloudAPI folder and select the SoundCloudAPI.xcodeproj file.

Adding files to your project
Select "Add Files to Project"
Select Xcode project files
Add Xcode project file to your project

Repeat the above steps for each of the submodules we added to the project: CocoaSoundCloudUI, JSONKit, OAuth2Client, and OHAttributedLabel.

Configuring your Workspace

Now that the SDK and dependencies have been added to your project, we'll need to configure your workspace to be able to find the header files and keep track of the various target dependencies and linker settings. First let's tackle headers. Click on your project in the Project Navigator, select Build Settings and search for "Header Search Paths". Add $PROJECT_DIR and select the checkbox to make it recursive. This will enable your project to search all of the submodules we added above when looking for header files.

Next, select Build Phases and click on the "+" icon under "Target Dependencies". When prompted, select libSoundCloudUI, OAuth2Client, libJSONKit, OHAttributedLabel and SoundCloudAPI.

Now click on the "+" icon under "Link Binary with Libraries". Add the following:

  • libJSONKit.a
  • libOAuth2Client.a
  • libOHAttributedLabel.a
  • libSoundCloudAPI.a
  • libSoundCloudUI.a
  • AddressBook.framework
  • AddressBookUI.framework
  • CoreGraphics.framework
  • CoreLocation.framework
  • CoreText.framework
  • QuartzCore.framework
  • Security.framework

To finish our linker settings, click on Build Settings again and search for "Other Linker Flags". Add -all_load -ObjC.

Some of the iOS components we'll need will require a few graphics. In your Project Navigator, expand the SoundCloudUI project and then expand the Resources folder. Drag SoundCloud.bundle to your project directory. A dialog will appear. Make sure to check the checkbox labelled "Copy items into destination group's folder (if needed) and then click the Finish button.

Congratulations! Your workspace should now be all set up to use the SoundCloud SDK. You can build and run your project (⌘ R) to make sure everything is working. Of course, your app is still just a grey box running on the iPhone simulator, so let's change that!

Authentication

Before you can make calls with the SoundCloud API, you must first set your client id and secret and give the user a chance to log in with their SoundCloud credentials.

Configuring your Application

Now that we've got our project created and dependencies installed, it's time to write some code. The first thing you'll need to do is set your client credentials. This is done by calling a method on the SCSoundCloud class. It's easiest to do this in the initialize class method in your app delegate, so open up SCTAppDelegate.m and add this near the top, underneath the @implementation SCTAppDelegate line:

+ (void) initialize
{
    [SCSoundCloud setClientID:@"YOUR_CLIENT_ID"
                       secret:@"YOUR_CLIENT_SECRET"
                  redirectURL:[NSURL URLWithString:@"sampleproject://oauth"]];
}

Make sure to add #import "SCUI.h" to the top of SCTAppDelegate.m as well.

Authenticating with the LoginViewController

Before we can use the SoundCloud API on behalf of a user, we have to give them an opportunity to log into our app with their SoundCloud credentials. The easiest way to do this on iOS is to use the LoginViewController. Select the SCTViewController.m file and add the following IBAction. Don't forget to also add #import "SCUI.h" to the top of the file.

- (IBAction) login:(id) sender
{
    SCLoginViewControllerCompletionHandler handler = ^(NSError *error) {
        if (SC_CANCELED(error)) {
            NSLog(@"Canceled!");
        } else if (error) {
            NSLog(@"Error: %@", [error localizedDescription]);
        } else {
            NSLog(@"Done!");
        }
    };

    [SCSoundCloud requestAccessWithPreparedAuthorizationURLHandler:^(NSURL *preparedURL) {
        SCLoginViewController *loginViewController;

        loginViewController = [SCLoginViewController
                               loginViewControllerWithPreparedURL:preparedURL
                                                completionHandler:handler];
        [self presentModalViewController:loginViewController animated:YES];
    }];
}

Now select the xib file and add a button, creating a connection to the action we just created. (Control + Drag the button to "File's Owner" and select "login" from the pop-up dialog).

After authenticating, the [SCSoundCloud account] accessor will return an authenticated instance that can be used to make requests against the API. If your app has not been authenticated, [SCSoundCloud account] will return nil.

Using the SoundCloud API

Now that the user has authenticated and authorized your application to make requests on their behalf, we're ready to start using the SoundCloud API. We'll add some basic functionality to our app that will fetch a list of sounds that the user has uploaded, and allow the user to play a sound. Later, we'll improve our app by allowing the user to upload sounds.

Get a List of Sounds

In order to get a list of sounds uploaded by the user, we'll use the [SCRequest performMethod] method. We'll need to store the list of tracks somewhere, so let's first create a UITableViewController. Make sure your project is selected in the Project Navigator, and select "New File" (⌘ N). Select "Objective-C class" when asked for the type of file to create. Name the class SCTTrackListViewController and make sure it's a subclass of UITableViewController. Also make sure that "With XIB for User Interface" is checked.

Adding a TableViewController
Your New File Dialog should look like this

We'll want somewhere to store the tracks, so add a property to your table view controller to store the tracks. We'll keep things simple and use an NSArray.

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface SCTTrackListViewController : UITableViewController <AVAudioPlayerDelegate>

@property (nonatomic, strong) NSArray *tracks;

@end

Make sure to add a corresponding @synthesize tracks; to the implementation file.

Now we'll need to create a button and corresponding action so the user can get a list of their sounds from their SoundCloud account. Add the following action method to your SCTViewController.m file. Then select the corresponding xib and create a button labelled "Get Tracks" as well as a connection to the action (Control drag the button to "File's Owner" and select getTracks).

Because we'll be using SCTTrackListViewController from this method, make sure to add #import "SCTTrackListViewController.h" to the top of the file.

- (IBAction) getTracks:(id) sender
{
    SCAccount *account = [SCSoundCloud account];
    if (account == nil) {
        UIAlertView *alert = [[UIAlertView alloc]
                              initWithTitle:@"Not Logged In"
                                    message:@"You must login first"
                                   delegate:nil
                          cancelButtonTitle:@"OK"
                          otherButtonTitles:nil];
        [alert show];
        return;
    }

    SCRequestResponseHandler handler;
    handler = ^(NSURLResponse *response, NSData *data, NSError *error) {
        NSError *jsonError = nil;
        NSJSONSerialization *jsonResponse = [NSJSONSerialization
                                             JSONObjectWithData:data
                                                        options:0
                                                          error:&jsonError];
        if (!jsonError && [jsonResponse isKindOfClass:[NSArray class]]) {
            SCTTrackListViewController *trackListVC;
            trackListVC = [[SCTTrackListViewController alloc]
                           initWithNibName:@"SCTTrackListViewController"
                                    bundle:nil];
            trackListVC.tracks = (NSArray *)jsonResponse;
            [self presentViewController:trackListVC
                               animated:YES completion:nil];
        }
    };

    NSString *resourceURL = @"https://api.soundcloud.com/me/tracks.json";
    [SCRequest performMethod:SCRequestMethodGET
                  onResource:[NSURL URLWithString:resourceURL]
             usingParameters:nil
                 withAccount:account
      sendingProgressHandler:nil
             responseHandler:handler];
}

Finally, we'll need to wire up our table view controller to use the tracks property as a data source. In order to do this we'll need to implement a number of methods defined in UITableViewController. There should be stubs already with most of the functionality commented out, since we specified that our controller subclasses UITableViewController. Find the commented out methods, remove them and replace them with the following:

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView
                      numberOfRowsInSection:(NSInteger)section
{
    return [self.tracks count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView
                   cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView
                    dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc]
                 initWithStyle:UITableViewCellStyleDefault
               reuseIdentifier:CellIdentifier];
    }

    NSDictionary *track = [self.tracks objectAtIndex:indexPath.row];
    cell.textLabel.text = [track objectForKey:@"title"];

    return cell;
}

Playing Sounds

Showing a list of sounds is great, but what good is a list of sounds if you can't play them? It'd be great if the user could tap on a sound and have it play, so let's build that functionality. We'll use the AVFoundation class AVAudioPlayer to play the file. Open your SCTTrackListViewController.h file and add a property for the player so your interface looks like this:

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface SCTTrackListViewController : UITableViewController

@property (nonatomic, strong) NSArray *tracks;
@property (nonatomic, strong) AVAudioPlayer *player;

@end

Don't forget to add @synthesize player; to the corresponding implementation file. Also, since we'll be using the audio player in this file, add #import <AVFoundation/AVFoundation.h> to the top of SCTTrackListViewController.m. Also, because we're using a class that's part of AVFoundation, we'll have to add that to our linked binaries. Click on your project file in the Project Navigator, select Build Phases and click on the '+' icon underneath "Link Binary With Libraries". Select AVFoundation.framework.

When a user taps a cell in a table view, the delegate's tableView:didSelectRowAtPath method is called with an index of the cell that was tapped. Open SCTTrackListViewController.m and find that method. Delete the existing code and make it look like this:

- (void)tableView:(UITableView *)tableView
         didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *track = [self.tracks objectAtIndex:indexPath.row];
    NSString *streamURL = [track objectForKey:@"stream_url"];

    SCAccount *account = [SCSoundCloud account];

    [SCRequest performMethod:SCRequestMethodGET
                  onResource:[NSURL URLWithString:streamURL]
             usingParameters:nil
                 withAccount:account
      sendingProgressHandler:nil
             responseHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                 NSError *playerError;
                 player = [[AVAudioPlayer alloc] initWithData:data error:&playerError];
                 [player prepareToPlay];
                 [player play];
             }];
}

Run your app to test that everything is working (⌘ R). You should be able to login, get a list of the users tracks and tap any track and it should start playing.

Uploading Sounds

Of course playing sounds is only one part of what you can do with the SoundCloud API. Let's now build upload functionality into your app. You could of course use [SCRequest performMethod] to send a POST request to the /tracks endpoint, but it's easier to use the SCShareViewController that comes with the SDK. Open SCTViewController.m and add the following action to your controller.

- (IBAction)upload:(id)sender
{
    NSURL *trackURL = [NSURL
          fileURLWithPath:[
              [NSBundle mainBundle]pathForResource:@"example" ofType:@"mp3"]];

    SCShareViewController *shareViewController;
    SCSharingViewControllerCompletionHandler handler;

    handler = ^(NSDictionary *trackInfo, NSError *error) {
        if (SC_CANCELED(error)) {
            NSLog(@"Canceled!");
        } else if (error) {
            NSLog(@"Error: %@", [error localizedDescription]);
        } else {
            NSLog(@"Uploaded track: %@", trackInfo);
        }
    };
    shareViewController = [SCShareViewController
                           shareViewControllerWithFileURL:trackURL
                                        completionHandler:handler];
    [shareViewController setTitle:@"Funny sounds"];
    [shareViewController setPrivate:YES];
    [self presentModalViewController:shareViewController animated:YES];
}

To keep things simple, this will upload a file called example.mp3. The same concept applies if you're building recording functionality into your app. To get this example working, create an mp3 and add it to your project.

Now open the corresponding xib file, add a button labelled "Upload" and connect it to the action we just created (Control drag the button to "File's Owner" and select "upload").

Wrap Up

Without too much work, we've managed to create an app that allows a user to authenticate with their SoundCloud credentials, list sounds they've uploaded, play them and upload new tracks.

If you'd like to explore further, check out the SDK Documentation on Github and of course, explore the rest of the documentation on this site. Particularly check out the API Reference section.