iOS Quickstart
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.
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.
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.alibOAuth2Client.alibOHAttributedLabel.alibSoundCloudAPI.alibSoundCloudUI.aAddressBook.frameworkAddressBookUI.frameworkCoreGraphics.frameworkCoreLocation.frameworkCoreText.frameworkQuartzCore.frameworkSecurity.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.
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.