TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Nov 2015 |
Maintained by Alfie Hanssen.
VIMUpload
is an Objective-C library that enables upload of videos to Vimeo. Its core component is a serial task queue that executes composite tasks (tasks with subtasks).
The upload system uses a background configured NSURLSession to manage a queue of video uploads (i.e. uploads continue regardless of whether the app is in the foreground or background). It can be configured to manage two background sessions if you plan on initiating uploads from within an app as well as an extension.
The upload queue can be paused and resumed, and it is automatically paused/resumed when losing/gaining an internet connection. It can also be configured to restrict uploads to wifi only.
The queue is persisted to disk so that in the event of an app termination event it can be reconstructed to the state it was in before termination.
If you're looking to interact with the Vimeo API for things other than video upload, check out VIMNetworking.
Check out the Pegasus sample project.
Add VIMUpload
and AFNetworking
(Release 2.5.4) as submodules of your git repository.
git submodule add [email protected]:vimeo/VIMUpload.git
git submodule add [email protected]:AFNetworking/AFNetworking.git
Add each submodule's classes to your project / target.
If you're also including VIMNetworking
in your project / target, note that both VIMUpload
and VIMNetworking
include the Certificate/digicert-sha2.cer
file (this file is used for cert pinning). You'll have to remove one of the digicert-sha2.cer
files from your target to avoid a "Multiple build commands for output file..." warning.
Subclass VIMTaskQueue
and implement a singleton object:
+ (instancetype)sharedAppQueue
{
static MYUploadTaskQueueSubclass *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// A background configuration with optional shared container identifier (if you plan on uploading from an extension)
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithID:@"your_session_identifier" sharedContainerID:@"your_optional_shared_container_identifier"];
VIMUploadSessionManager *sessionManager = [[VIMUploadSessionManager alloc] initWithSessionConfiguration:configuration];
sessionManager.requestSerializer = ...;
// Where client.requestSerializer is an AFJSONRequestSerializer subclass that serializes the following information on each request:
// [serializer setValue:@"application/vnd.vimeo.*+json; version=3.2" forHTTPHeaderField:@"Accept"];
// [serializer setValue:@"Bearer your_oauth_token" forHTTPHeaderField:@"Authorization"];
sharedInstance = [[self alloc] initWithSessionManager:sessionManager];
});
return sharedInstance;
}
If you plan to initiate uploads from an extension, you will need to use a separate instance of VIMUploadTaskQueue
, initialized with a separate VIMNetworkTaskSessionManager
, initialized with a separate background session identifier.
Load your VIMUploadTaskQueue
(s) at each app launch.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// ...
[MYUploadTaskQueueSubclass sharedAppQueue];
[MYUploadTaskQueueSubclass sharedExtensionQueue];
return YES;
}
Implement the application:handleEventsForBackgroundURLSession:completionHandler:
method in your AppDelegate:
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
if ([identifier isEqualToString:[MYUploadTaskQueueSubclass sharedAppQueue].sessionManager.session.configuration.identifier])
{
[MYUploadTaskQueueSubclass sharedAppQueue].sessionManager.completionHandler = completionHandler;
}
else if ([identifier isEqualToString:[MYUploadTaskQueueSubclass sharedExtensionQueue].sessionManager.session.configuration.identifier])
{
[MYUploadTaskQueueSubclass sharedExtensionQueue].sessionManager.completionHandler = completionHandler;
}
}
Enqueue a PHAsset
for upload.
PHAsset *asset = ...;
VIMVideoAsset *videoAsset = [[VIMVideoAsset alloc] initWithPHAsset:asset];
[[MYUploadTaskQueueSubclass sharedAppQueue] uploadVideoAssets:@[videoAsset]];
Enqueue an AVURLAsset
for upload.
NSURL *URL = ...;
AVURLAsset *URLAsset = [AVURLAsset assetWithURL:URL];
BOOL canUploadFromSource = ...; // If the asset doesn't need to be copied to a tmp directory before upload, set this to YES
VIMVideoAsset *videoAsset = [[VIMVideoAsset alloc] initWithURLAsset:URLAsset canUploadFromSource:canUploadFromSource];
[[MYUploadTaskQueueSubclass sharedAppQueue] uploadVideoAssets:@[videoAsset]];
Enqueue multiple assets for upload.
NSArray *videoAssets = @[...];
[[MYUploadTaskQueueSubclass sharedAppQueue] uploadVideoAssets:videoAssets];
Cancel an upload.
VIMVideoAsset *videoAsset = ...;
[[MYUploadTaskQueueSubclass sharedAppQueue] cancelUploadForVideoAsset:videoAsset];
Cancel all uploads.
[[MYUploadTaskQueueSubclass sharedAppQueue] cancelAllUploads];
Pause all uploads.
[[MYUploadTaskQueueSubclass sharedAppQueue] pause];
Resume all uploads.
[[MYUploadTaskQueueSubclass sharedAppQueue] resume];
Ensure that uploads only occur when connected via wifi...or not. If cellularUploadEnabled
is set to NO
, the upload queue will automatically pause when leaving wifi and automatically resume when entering wifi. (Note: the queue will automatically pause/resume when the device is taken offline/online.)
[MYUploadTaskQueueSubclass sharedAppQueue].cellularUploadEnabled = NO;
Add video metadata to an enqueued or in-progress upload.
VIMVideoAsset *videoAsset = ...;
VIMVideoMetadata *videoMetadata = [[VIMVideoMetadata alloc] init];
videoMetadata.videoTitle = @"Really cool title";
videoMetadata.videoDescription = @"Really cool description"";
videoMetadata.videoPrivacy = (NSString *)VIMPrivacyValue_Private;
[[MYUploadTaskQueueSubclass sharedAppQueue] addMetadata:videoMetadata toVideoAsset:videoAsset withCompletionBlock:^(BOOL didAdd) {
if (!didAdd)
{
// The upload has already finished,
// Set the metadata using the VIMAPIClient method updateVideoWithURI:title:description:privacy:completionHandler:
}
}];
If you build UI to support pause and resume, listen for the VIMNetworkTaskQueue_DidSuspendOrResumeNotification
notification and update your UI accordingly.
- (void)addObservers
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(uploadTaskQueueDidSuspendOrResume:) name:VIMNetworkTaskQueue_DidSuspendOrResumeNotification object:nil];
}
- (void)uploadTaskQueueDidSuspendOrResume:(NSNotification *)notification
{
BOOL isSuspended = [[MYUploadTaskQueueSubclass sharedAppQueue] isSuspended];
[self.pauseResumeButton setSelected:isSuspended];
}
Use KVO to communicate upload state and upload progress via your UI. Observe changes to VIMVideoAsset
's uploadState
and uploadProgressFraction
properties.
static void *UploadStateContext = &UploadStateContext;
static void *UploadProgressContext = &UploadProgressContext;
- (void)addObservers
{
[self.videoAsset addObserver:self forKeyPath:NSStringFromSelector(@selector(uploadState)) options:NSKeyValueObservingOptionNew context:UploadStateContext];
[self.videoAsset addObserver:self forKeyPath:NSStringFromSelector(@selector(uploadProgressFraction)) options:NSKeyValueObservingOptionNew context:UploadProgressContext];
}
- (void)removeObservers
{
@try
{
[self.videoAsset removeObserver:self forKeyPath:NSStringFromSelector(@selector(uploadState)) context:UploadStateContext];
}
@catch (NSException *exception)
{
NSLog(@"Exception removing observer: %@", exception);
}
@try
{
[self.videoAsset removeObserver:self forKeyPath:NSStringFromSelector(@selector(uploadProgressFraction)) context:UploadProgressContext];
}
@catch (NSException *exception)
{
NSLog(@"Exception removing observer: %@", exception);
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if (context == UploadStateContext)
{
if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadState))])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self uploadStateDidChange];
});
}
}
else if (context == UploadProgressContext)
{
if ([keyPath isEqualToString:NSStringFromSelector(@selector(uploadProgressFraction))])
{
dispatch_async(dispatch_get_main_queue(), ^{
[self uploadProgressDidChange];
});
}
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
When your UI is loaded or refreshed, associate your newly create VIMVideoAsset objects with their upload task counterparts so your UI continues to communicate upload state and progress.
NSArray *videoAssets = self.datasource.items; // For example
[[MYUploadTaskQueueSubclass sharedAppQueue] associateVideoAssetsWithUploads:videoAssets];
VIMUpload
is available under the MIT license. See the LICENSE file for more info.
Tweet at us here: @vimeoapi
Post on Stackoverflow with the tag vimeo-ios
Get in touch here