Documentation

Getting Started:

Sharing:

Creating Services:

Managing Services

How to Share

This documentation already assumes you've installed ShareKit. If you have not done that, I would recommend following the install instructions to familarize yourself with ShareKit.

As described by the install documentation, to launch ShareKit, you create an SHKItem to share, a SHKActionSheet with the item, and then display the SHKActionSheet to the user:

- (void)myButtonHandlerAction
{
	// Create the item to share (in this example, a url)
	NSURL *url = [NSURL URLWithString:@"http://getsharekit.com"];
	SHKItem *item = [SHKItem URL:url title:@"ShareKit is Awesome!"];

	// Get the ShareKit action sheet
	SHKActionSheet *actionSheet = [SHKActionSheet actionSheetForItem:item];

	// Display the action sheet
	[actionSheet showFromToolbar:navigationController.toolbar];
}

 

SHKItem has four methods, one for each type of file that you want to share.

Sharing URLs

+ (SHKItem *)URL:(NSURL *)url title:(NSString *)title;

url - The URL you want to share
title - (optional nil) - The title of the URL

// Create the item to share (in this example, a url)
NSURL *url = [NSURL URLWithString:@"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:@"ShareKit is Awesome!"];

If you are sharing a page a user is viewing in a UIWebView, a category is provided to extract the page title from the page. Import "SHK.h" to the top of your class and call:

NSString *title = [myWebView pageTitle];

// which can be used like:
SHKItem *item = [SHKItem URL:myWebView.request.URL title:title];

Sharing Images

+ (SHKItem *)image:(UIImage *)image title:(NSString *)title;

image - The image you want to share
title - (optional nil) - The title of the image

// Example: Use an image in our resource bundle
UIImage *image = [UIImage imageNamed:@"sanFran.jpg"];
SHKItem *item = [SHKItem image:image title:@"Look at this picture!"];

Sharing Text

+ (SHKItem *)text:(NSString *)text;

text - The text you want to share

NSString *someText = @"This is a blurb of text I highlighted from a document.";
SHKItem *item = [SHKItem text:someText];

Sharing Files

+ (SHKItem *)file:(NSData *)data filename:(NSString *)filename mimeType:(NSString *)mimeType title:(NSString *)title;

data - the contents of the file you want to share
filename - the suggested filename (ex: myFile.doc)
mimeType - the mime-type of the file
title - the name of the file

NSData *myPDF = [NSData dataWithContentsOfFile:@"path/to/my/file.pdf"];
SHKItem *item = [SHKItem file:myPDF 
		filename:@"file.pdf" 
		mimeType:@"application/pdf" 
		title:@"A PDF file for you"];

Sharing with a Specific Service

If you create your own interface for ShareKit or have a reason to share directly with a specific service, it's just as easy as calling the actionsheet.

You simply create a SHKItem and then push the item to the service's class. Here is an example of sharing a URL with Read It Later:

#import "SHKReadItLater.h" //include the service's header at the top of your class

...

// Create the item to share (in this example, a url)
NSURL *url = [NSURL URLWithString:@"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:@"ShareKit is Awesome!"];

// Share the item
[SHKReadItLater shareItem:item];

To share other types of content, see How to share above.

Sharing Offline

If your app can be used without an internet connection, you should support offline sharing. Luckily, this means only adding one additional line of code.

Most ShareKit services support offline sharing. This means when a user shares something while they are disconnected, ShareKit will store it and wait to send until they are connected again.

You just need to tell ShareKit when to retry these offline items. A good time to do this is when the app is opened. Simply add this line when you want ShareKit to try resending the items:

[SHK flushOfflineQueue];

Creating New Services

Understanding the Share Flow

There are 3 phases a service class will respond to. Here is a quick overview of what happens when a user clicks a share button that is hooked up to ShareKit.

Step 1 : CanShare...?

The first thing ShareKit will do is gather a list of services that can respond to the item being shared. If for example, the user wants to share a URL, it will call +(BOOL)canShareURL on your service class to see if you accept URLs. If your service can share URLs, you should return YES.

// Other types to respond to:
+ (BOOL)canShareURL
+ (BOOL)canShareImage
+ (BOOL)canShareText
+ (BOOL)canShareFile

Step 2 : Authentication

After a user has selected which service to use, ShareKit looks to see if it has stored credentials for the service. If it does not, it attempts to authenticate the user before sharing. This step is different depending on the type of service you are creating (action, web, web w/ OAuth).

Authenticating Actions

Generally actions should not require authenticating. If they connect to a web service, you should use the web service template instead.

Authenticating Web Services

ShareKit will call -(NSArray *)authorizationFormFields on your class to get a login form to display to the user. You should return the fields required to log a user in to your service.
See using Forms for more on creating a form.

The form is then displayed to the user. Once they complete their information, they will hit 'Login'. This calls -(void)authorizationFormValidate:(SHKFormController *)form on your class.

In authorizationFormValidate, you will validate the form data and then send a request to your server to verify the provided credentials are correct. You are responsible for sending the request and handling and displaying errors (i.e. incorrect username and password).

Once the user's credentials have been verified, you'll save the form and ShareKit will continue on to the next step.

Authenticating Web Services with OAuth

If your service uses OAuth, most of the work is already done for you. ShareKit will use the provided token request, authorize, and access URLs along with the app's consumer and secret keys to do the complete OAuth roundtrip on its own.

Step 3 : Presenting an Edit Form

ShareKit will first check to see if the user has enabled auto-sharing for your service. Auto sharing allows the user to skip the share dialog. For example, when a user shares with Delicious, they can edit the title, add tags, and set the privacy setting of the shared item. If a user wants to skip this step, they can toggle on auto-share and ShareKit will just immediately share the item the next time they use Delicious.

If your service has additional information that is required, you can disable this by responding NO to - (BOOL)canAutoShare

Next ShareKit calls -(NSArray *)shareFormFieldsForType:(SHKShareType)type to request a form to let the user edit the item they are sharing or provide additional details. If you do not require any other information, do not provide this method and the form will be skipped.
See using Forms for more on creating a form.

Step 4 : Sending the item

Finally, ShareKit will attempt to send the item by calling -(BOOL)send.

Here you should do whatever is necessary to send the item to your service or perform the required action.

At this point you'll likely need information about the shared item and access to the stored credentials for the user. See the following sections for retrieving both:

If the action is asynchronous and will not be completed by the time send returns (which is likely to be the case for all web services), you need to update ShareKit and tell it what is happening. There are five methods you can call on your own service class:

[self sendDidStart];
This notifies ShareKit that you have started sending the item. ShareKit will present an activity indicator to the user.

[self sendDidFinish];
This notifies ShareKit that the item was sent successfully. ShareKit will display a 'Saved!' message and close any open ShareKit views.

[self sendDidFailShouldRelogin];
If the send request fails because the user's credentials are no longer accurate, use this and ShareKit will attempt to reauthenticate the user (Step 2 above).

[self sendDidFailWithError:(NSError *)];
This notifies ShareKit that sending the item has failed. It will display an error to user.

[self sendDidCancel];
This tells ShareKit that the user cancelled the share. Most implementations will not call this.

Using Forms

There are two places where ShareKit will present a form to the user: when logging in and when allowing them to edit an item before it is shared.

ShareKit takes care of displaying and storing the data collected from the form. You simply need to tell it what questions to ask.

The two instances where ShareKit will request form fields from your service are:
(NSArray *)shareFormFieldsForType:(SHKShareType)type
(NSArray *)authorizationFormFields

Each method should return a NSArray of SHKFormFieldSetting objects.

A SHKFormFieldSetting is made up of:
- a label : The question being asked
- a key : The key by which you'll retrieve the data later (like a variable name)
- a type : The type of field, either SHKFormFieldTypeText, SHKFormFieldTypePassword, or SHKFormFieldTypeSwitch
- a starting value : If the field should be prefilled, provide a starting value. For SHKFormFieldTypeSwitch fields, this can be either SHKFormFieldSwitchOn or SHKFormFieldSwitchOff.

You create a SHKFormFieldSetting object with one line:

SHKFormFieldSettings *field = 
[SHKFormFieldSettings label:@"My Label"
 key:@"myKey" 
 type:SHKFormFieldTypeText 
 start:nil];

Some examples

Generally an authorization form will just ask for a username and password. That looks like:

- (NSArray *)authorizationFormFields
{
	return [NSArray arrayWithObjects:
			[SHKFormFieldSettings label:@"Username"
	                                      key:@"username"
	                                      type:SHKFormFieldTypeText
	                                      start:nil],
			[SHKFormFieldSettings label:@"Password"
	                                      key:@"password"
	                                      type:SHKFormFieldTypePassword
	                                      start:nil],			
			nil];
}

An edit share item form may ask for more details. Here is an example:

- (NSArray *)shareFormFieldsForType:(SHKShareType)type
{
	return [NSArray arrayWithObjects:
    		
            // Let the user edit the item's title before sending.
            // Use item.title as the starting value to prefill the existing title
            // Use "title" as the key so when the form is saved, it overwrites the
            // item's title property
			[SHKFormFieldSettings label:@"Title"
	                                      key:@"title"
	                                      type:SHKFormFieldTypeText
	                                      start:item.title],
            
            // If your service let's users make their items public, you may want
            // to add an option to make the share public or private.
            // Here we add a UISwitch to the form and save it to the item 
            // with the 'public' key. We also set the switch to start as OFF
            // so by default the share is private
			[SHKFormFieldSettings label:@"Public"
	                                      key:@"public"
	                                      type:SHKFormFieldTypeSwitch
	                                      start:SHKFormFieldSwitchOff],			
			nil];
}

Validating the data

You'll likely need to validate the data in the form before saving.

Instances where you'll need to do this are:
- (void)shareFormValidate:(SHKCustomFormController *)form
- (void)authorizationFormValidate:(SHKFormController *)form

When the form is being displayed and you have access to the SHKFormController object, you can access the form data with [theForm formValues]. This will return a NSDictionary of each field's 'key' value mapped to a key in the dictionary.

If the data looks good and can be saved, call [form saveForm]. On the authentication form, this will save the values to the keychain and for the share form, the values will be saved to the SHKItem. See the next section on retrieving this data.

Retrieving the data

To retrieve the data collected from a login form, see Getting stored logins.

To retrieve the data collected from a share/edit form, see Using SHKItem.

Accessing SHKItem

Everything in ShareKit revolves around SHKItem. It stores everything there is to know about something that is being shared. You should be familar with accessing the information stored in SHKItem so your service can use it correctly.

There are several built-in properties that you can find/store values in:


// This indicates what type of content is stored in the item.
SHKShareType shareType;
// Possible values:
// SHKShareTypeURL, SHKShareTypeImage, SHKShareTypeText, SHKShareTypeFile

// This is generally used for url sharing (SHKShareTypeURL)
NSURL *URL;

// This is generally used for image sharing (SHKShareTypeImage)
UIImage *image;

// These text related properties are used for all 4 types
NSString *title; // use for any title or subject type field
NSString *text; // use for any long text like a note, SHKShareTypeText uses this
NSString *tags; // use for tagging
	
// These are used for file sharing (SHKShareTypeFile)
NSData *data;
NSString *mimeType;
NSString *filename;

Setting and Storing Custom Values

Your service may have additional values that it needs to collect when sharing. You can set and retrieve custom variables from SHKItem. Custom values can only be NSStrings. This is so that they can be stored for offline use if your service supports offline sharing.

// Saving a custom value
[item setCustomValue:@"This is my value" forKey:@"myCustomKey"];

// Retrieving the value
NSString *value = [item customValueForKey:@myCustomKey"];
// value = @"This is my value"

Using with Forms

When using forms, setting any form key name to an item's property name will cause the item's property to be overwritten with that value when the form is saved.

If the form's key does not match a property, it will be saved as a custom value.


// A SHKFormFieldSetting mapped to the item's tags property:
[SHKFormFieldSettings label:@"Tags"
 key:@"tags" // use of 'tags' here maps it to the item's tag property
 type:SHKFormFieldTypeText 
 start:item.tags]; // display the current item.tags value in the form
 
// After the form is saved, the result can be retrieved by 
item.tags

..

// A SHKFormFieldSetting mapped to an item's custom value:
[SHKFormFieldSettings label:@"Custom Question"
 key:@"myCustomKey" 
 type:SHKFormFieldTypeText 
 start:nil];
 
// After the form is saved, the result can be retrieved by 
NSString *value = [item customValueForKey:@"myCustomKey"];

..

// An example using a switch and the BOOL convenience method
[SHKFormFieldSettings label:@"Public"
 key:@"myCustomKey" 
 type:SHKFormFieldTypeSwitch 
 start:nil];
 
// Can be retrieved by
BOOL isPublic = [item customBoolForSwitchKey:@"myCustomKey"];

Accessing Stored Logins

If your web service uses basic auth, you'll likely need to send the username and password along with the shared item. After a user has been authenticated, the credentials are stored and easily accessible.


// To retrieve a stored value:
// self = your service class
// In this example, let's retrieve the username and password:
NSString *username = [self getAuthValueForKey:@"username"];
NSString *password = [self getAuthValueForKey:@"password"];


// The keys used to retrieve the data are the same keys you used 
// when defining your login form:
- (NSArray *)authorizationFormFields
{
	return [NSArray arrayWithObjects:
			[SHKFormFieldSettings label:@"Username"
	                                      key:@"username" <---
	                                      type:SHKFormFieldTypeText
	                                      start:nil],
			[SHKFormFieldSettings label:@"Password"
	                                      key:@"password" <---
	                                      type:SHKFormFieldTypePassword
	                                      start:nil],			
			nil];
}

Logging Out / Removing Stored Logins

There are three methods to remove stored credentials:

// Remove credentials for all services
[SHK logoutOfAll];

// Remove credentials for a specific service
// Use the service's class name: ex SHKTwitter, SHKDelicious
[SHK logoutOfService:@"SHKReadItLater"];

// Remove credentials for a specific service (alternative method)
// call +logout on any sharer class
[SHKTwitter logout];

Using SHKRequest

You can use whatever methods you'd like to connect to your web service. If all you need is a way to send a few parameters to a specific URL and get the response, the SHKRequest object will help you get started quickly.


- (BOOL)send
{
    // Set the parameters for the request
    // Create a parameter string like you would for a GET request
    NSString *params = [NSMutableString stringWithFormat:@"username=%@&password=%@",
        SHKEncode([self authValueForKey:@"username"]),
        SHKEncode([self authValueForKey:@"password"])
    ];
    
    // Other helpers:
    // SHKEncode() takes a string and properly urlencodes it.
    // SHKEncodeURL() takes a NSURL and properly urlencodes it into a string.
    
    // Send request
    NSURL *url = [NSURL URLWithString:@"http://api.example.com/share/"];
    self.request = [[[SHKRequest alloc] initWithURL:url
        params:params
        delegate:self
        isFinishedSelector:@selector(sendFinished:) // set your callback function
        method:@"POST" // POST or GET
        autostart:YES] autorelease];
}

// a callback (as set by isFinishedSelector above)
- (void)sendFinished:(SHKRequest *)aRequest
{
    // If the request status code was 200, 'success' will be set to YES
    if (aRequest.success)
    {
        // Do something with the result
        NSString *bodyOfResponse = [aRequest getResult];        
    }
    
    // If there is an error, handle it
    else
    {
        // SHKRequest has a few properties that can help find out what happened
        // aRequest.response is the NSHTTPURLResponse of the request
        // aRequest.response.statusCode is the HTTTP status code of the response
        // [aRequest getResult] returns a NSString of the body of the response
        
        
        // What was the status code?
        int HTTPstatusCode = aRequest.response.statusCode; // 404? 401? 500?
        
        // What was the value of some header value?
        NSString *contentType = [aRequest.headers objectForKey:@"Content-Type"];
    }
}