iOS SDK  3.5.0.104555
 All Classes Files Functions Variables Properties Macros Pages
Transferring Files

In using the SDK to transfer files one interacts primarily with the following classes:

Asynchronous interaction with the transfer queue occurs via a class conforming to ASTransferQueueDelegate that is to be provided by the user.

Initialization

Before any files are transferred the SDK must be initialized:

Objective-C     Swift
NSError *error = nil;
if (error != nil)
[NSException raise:@"Error initializaing SDK"
format:@"description: %@",
[error localizedDescription]];
var err: NSError?
AsperaMobile.initializeWithLogLevel(0, error: &err)
if let actualError = err {
NSException.raise("Init railed", format:"%@", arguments: getVaList(["\(actualError.localizedDescription)"]))
}

Creating Sessions

When creating a session we must provide it with a minimal set of information: an account with host and credentials, a transfer direction and at least one file to transfer:

Objective-C     Swift
ASAccount *account;
ASFaspSession *session;
account = [ASAccount accountWithHost:@"example.com" user:@"usr" password:@"pw" sshPort:22 udpPort:33001];
session = [ASFaspSession sessionWithAccount:account upload:YES];
[session addPath:@"path/to/file1/"];
let account = ASAccount(host: "example.com", user: "usr", password: "pw", sshPort: 22, udpPort: 33001)
let session = ASFaspSession(account: account, upload: true)
session.addPath("path/to/file1/")

Since we passed YES to the parameter 'upload:' this session the path added would be interpreted relative to the docroot on the remote machine.

If the very next thing intended for this session is to add it to the queue then there is nothing else to do. If, on the other hand, the session will not be immediately enqueued then it is necessary to manually save it. See Multi-Threaded Environments for more information.

Warning
Previous versions of the SDK expected absolute paths for uploads. Such use is discouraged and use of paths relative to the embedding application's documents directory is encouraged instead. Use of absolute paths for uploads can cause problems with persisted sessions across upgrades, where the application's path may change rendering any persisted sessions invalid

Enqueuing Sessions

Once a session has been populated, enqueuing it is a simple matter:

Objective-C     Swift
ASFaspSession *s1, *s2; /* Assume s1, s2 have been populated */
[queue enqueueSession:s1];
[queue enqueueSession:s2];
var s1, s2 : ASFaspSession /* Assume s1, s2 have been populated */
let queue = ASTransferQueue.sharedQueue()
queue.enqueueSession(s1)
queue.enqueueSession(s2)

The first session is enqueued at index 0, the second at index 1, and so on. Sessions are executed in the same order in which they were enqueued (assuming the queue has been started).

Interrupting Transfers

ASTransferQueue contains several different mechanisms for interrupting active sessions in the queue. Each results in an interruption to the transfer but the subsequent behavior of the queue varies. The most common use is to cancel a session (cancelSessionAtIndex: (ASTransferQueue)). Cancelling a session will interrupt the transfer, deactivate it and prevent it from being automatically re-run by the queue again. Cancelled sessions remain in the queue and can be re-run at any time using runSessionAtIndex: (ASTransferQueue).

Another mechanism for interrupting an active session is to run a different session using runSessionAtIndex:. If this method is called with the index of session B while session A is active, the queue will stop session A and start session B. Once session B finishes, session A will resume. Once session A finishes, the queue will continue activating sessions according to their order in the queue.

Two final mechanisms for interrupting active sessions are pausing sessions and stopping sessions. These are less commonly used. Pausing a session will not deactivate it, so it blocks the queue until it is resumed (or otherwise terminates), while stopping a session is much like canceling a session except that the session will be automatically re-run at a later time by the queue. Consult the documentation for pauseSessionAtIndex: (ASTransferQueue) and stopSessionAtIndex: (ASTransferQueue) for more information.

Note
the method resumeSessionAtIndex: is intended to be used with sessions previously interrupted using pauseSessionAtIndex:. In order to re-run sessions that have been interrupted using cancelSessionAtIndex:, use runSessionAtIndex: instead.

Starting and Stopping the Queue

An ASTransferQueue has two modes: stopped and running. A stopped queue is completely passive, while a running queue maintains an active background thread which is responsible for executing any pending transfers. Starting the queue is straightforward:

Objective-C     Swift
let queue = ASTransferQueue.sharedQueue()
queue.start()

Normally, the queue may be started when an application is initialized and left running for the entire duration of the application's lifetime (even when that application transitions to and from the background). In some situations, however, it may be desirable to stop the queue. This is equally straightforward:

Objective-C     Swift
let queue = ASTransferQueue.sharedQueue()
queue.stop()

Both methods return immediately. In the case of stop (ASTransferQueue) the queue will first stop any ongoing session and only then terminate the background thread, thereby transitioning into the stopped state. In general, when next started the queue will pick up the same transfer it had last been transferring (an exception is if the queue had been modified in particular ways while stopped, for instance by adding sessions to the front of the queue)

Monitoring Queue Activity

In order to monitor queue activity - including addition and removal of sessions to the queue and individual session progress - one must implement a queue delegate conforming to ASTransferQueueDelegate.

The queue delegate protocol provides a fair number of delegate methods, each corresponding to different points in session life cycle or general management that may be leveraged to update a UI or otherwise respond to transfer events (but see the warning below the example). It is designed with UITableViews in mind, and all the methods are optional. For the purposes of demonstration only several delegate call implementations are shown here:

Objective-C     Swift
@implementation MyQueueDelegate <ASTransferQueueDelegate>
// ...
// Invocation marks begining of a set of queue callbacks
// other than willChangeQueue or didChangeQueue
- (void)willChangeQueue:(ASTransferQueue *)queue {
NSLog(@"WILL CHANGE QUEUE");
}
// Invocation marks end of a set of queue callbacks
// other than willChangeQueue or didChangeQueue
- (void)didChangeQueue:(ASTransferQueue *)queue {
NSLog(@"DID CHANGE QUEUE");
}
// Invocation signifies addition of a session to the queue
- (void)queue:(ASTransferQueue *)queue didAddSessionAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"DID CHANGE QUEUE AT INDEX: %u", [path row]);
}
// Invocation signifies that progress changed for a running session,
// access to transfer stats demonstrated
- (void)queue:(ASTransferQueue *)queue progressChangedForSessionAtIndexPath:(NSIndexPath *)path {
NSLog(@"PROGRESS FOR SESSION AT INDEX: %u", [path row]);
ASTransferSession *session = [queue sessionAtIndex:[path row]];
ASTransferStats *stats = [session transferStats];
NSLog(@"\n");
NSLog(@"total size: %@", [stats totalSize]);
NSLog(@"total sent: %@", [stats totalWritten]);
NSLog(@"time elapsed: %@", [stats timeElapsed]);
NSLog(@"avg rate: %@", [stats averageTransferRate]);
NSLog(@"time remaining: %@", [stats averageTimeRemaining]);
NSLog(@"\n");
}
// ...
@end
class MyQueueDelegate: ASTransferQueueDelegate {
// ...
// Invocation marks begining of a set of queue callbacks
// other than willChangeQueue or didChangeQueue
func willChangeQueue(queue: ASTransferQueue!) {
NSLog("WILL CHANGE QUEUE")
}
// Invocation marks end of a set of queue callbacks
// other than willChangeQueue or didChangeQueue
func didChangeQueue(queue: ASTransferQueue!) {
NSLog("DID CHANGE QUEUE")
}
// Invocation signifies addition of a session to the queue
func queue(queue: ASTransferQueue!, didAddSessionAtIndexPath indexPath: NSIndexPath!) {
NSLog("DID CHANGE QUEUE AT INDEX: %u", path.row)
}
// Invocation signifies that progress changed for a running session,
// access to transfer stats demonstrated
func queue(queue: ASTransferQueue!, progressChangedForSessionAtIndexPath indexPath: NSIndexPath!) {
NSLog("PROGRESS FOR SESSION AT INDEX: %u", path.row)
let session = queue.sessionAtIndex((Uint)path.row)
let stats = session.transferStats
NSLog("\n")
NSLog("total size: %@", stats.totalSize())
NSLog("total sent: %@", stats.totalWritten())
NSLog("time elapsed: %@", stats.timeElapsed())
NSLog("avg rate: %@", stats.averageTransferRate())
NSLog("time remaining: %@", stats.averageTimeRemaining())
NSLog("\n")
}
// ...
}

Note that for delegate events to be triggered one must first set the queue delegate (see ASTransferQueue::delegate for more information)

Warning
Queue delegate methods execute on a background thread, and the reader is reminded that UIKit is in general not thread safe. If you wish to update UI components from queue delegate methods, be sure to do so indirectly by scheduling these updates on the main thread. One possible way to do that is to use blocks:
Objective-C     Swift
- (void)queue:(ASTransferQueue *)queue progressChangedForSessionAtIndexPath:(NSIndexPath *)path {
dispatch_async( dispatch_get_main_queue(), ^{
// Update UI elements here
});
}
func queue(queue: ASTransferQueue!, progressChangedForSessionAtIndexPath indexPath: NSIndexPath!) {
dispatch_async( dispatch_get_main_queue(), {
// Update UI elements here
});
}

Transferring in the Background

Versions 4 and 5 of iOS place restrictions on what types of applications may run in the background, and for how long. By default the Aspera iOS SDK will declare its transfers to the OS as background tasks of finite length, making it so that transfers will continue to run even if the embedding application transitions to the background (this can be disabled if undesirable, see ASTransferQueue::backgroundTaskDemarcationEnabled). These transfers may not complete as iOS does not as of yet allow such tasks to run indefinitely - if they reach the limit allowed to run in the background, all transfers will be stopped.

iOS also provides several other mechanisms for specific types of applications (such as VOIP or location-aware applications) to run in the background. These mechanisms are not leveraged in the SDK, solely that of finite-length background tasks. Furthermore the SDK will not interact or interfere with any other mechanisms used to facilitate running in the background (including other finite-length background tasks).

Cleanup

A session and its associated account are persisted when a session is added to the queue. This means that sessions and accounts, once added, will be around on all future occasions that the application runs - unless they are removed. If at some point in your application's operation it becomes desirable to permanently remove one of these instances this may be done by invoking their respective delete methods:

Objective-C     Swift
/* session, account are instances of ASFaspSession, ASAccount */
/* ... */
[session delete];
[account delete];
/* session, account are instances of ASFaspSession, ASAccount */
/* ... */
session.delete()
account.delete()

Removing a session from the queue will delete it, so manually deleting sessions is usually not necessary. Note also that running sessions should not be deleted. Account deletion will fail if there are any existent sessions that reference the account being deleted.