Need to see if your shared folder is taking up space on your dropbox 👨💻? Find out how to check here.
Forum Discussion
Robert S.138
10 years agoHelpful | Level 7
Threads, tasks, and the Objective-C SDK
Having completed an Android version of my app, I was hoping that the Objective-C version for iOS would be similar. But looking at the DBRoulette example, there seems to be a big difference regarding...
Stephen C.14
Dropbox Staff
10 years ago@Robert S: I wouldn't recommend using `sleep` like that. I'd instead maintain references to each task object and then `cancel` each task object when the user cancels. I took a bit of time and wrote up what a solution might look like. It took me longer than I thought, which might be an indication that the SDK needs richer functionality.
Try this out and let me know how it works. I think it might be easier pulling the file directly: DownloadFolder.m
@interface MyClass ()@property (atomic) DropboxClient * _Nullable client;@property (atomic) NSOperationQueue * _Nullable responseQueue;@property (atomic) NSFileManager * _Nullable fileManager;@property (atomic) BOOL shouldContinue;@property (atomic) NSLock *shouldContinueLock;@property (atomic) NSMutableDictionary<NSString *, DBRpcTask *> *rpcTasks;@property (atomic) NSMutableDictionary<NSString *, DBDownloadUrlTask *> *downloadUrlTasks;@property (atomic) NSLock *tasksLock;@end@implementation MyClass- (void)initAndLaunch {NSLog(@"\n\n\nInitializing on: %@", [NSThread currentThread]);_client = [DropboxClientsManager authorizedClient];_responseQueue = [NSOperationQueue new];[_responseQueue setMaxConcurrentOperationCount:1];_fileManager = [NSFileManager defaultManager];_shouldContinue = YES;_shouldContinueLock = [NSLock new];_rpcTasks = [NSMutableDictionary new];_downloadUrlTasks = [NSMutableDictionary new];_tasksLock = [NSLock new];NSURL *outputUrl = [_fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];outputUrl = [outputUrl URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", @"MyOutputFolder", [NSUUID UUID].UUIDString]];[self downloadFolder:@" outputUrl:outputUrl];// cancel the download after 5 secondsdouble delayInSeconds = 5.0;dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));dispatch_after(popTime, dispatch_get_main_queue(), ^(void){[self cancelDownload];});}- (void)downloadFolder:(NSString *)inputPath outputUrl:(NSURL *)outputUrl {NSLog(@"Downloading all files from: \"%@\" to \"%@\", inputPath, outputUrl);[_responseQueue addOperationWithBlock:^{[self downloadFolderHelper:inputPath outputUrl:outputUrl];}];}- (void)downloadFolderHelper:(NSString *)inputPath outputUrl:(NSURL *)outputUrl {NSLog(@"Commencing folder download on: %@", [NSThread currentThread]);NSString *listFolderTaskKey = [NSString stringWithFormat:@"ListFolderTask.%@", [NSUUID UUID].UUIDString];[self.shouldContinueLock lock];if (!_shouldContinue) {NSLog(@"No longer continuing...");[self.shouldContinueLock unlock];return;}DBRpcTask *listFolderTask = [self listFolder:inputPath outputUrl:outputUrl listFolderTaskKey:listFolderTaskKey];[self.rpcTasks setObject:listFolderTask forKey:listFolderTaskKey];[self.shouldContinueLock unlock];}-(DBRpcTask *)listFolder:(NSString *)inputPath outputUrl:(NSURL *)outputUrl listFolderTaskKey:(NSString *)listFolderTaskKey {DBRpcTask *listFolderTask = [[_client.filesRoutes listFolder:inputPath]response:_responseQueue response:^(DBFILESListFolderResult *listFolderResult, DBFILESListFolderError *routeError, DBError *error) {NSLog(@"Handling list folder response on: %@", [NSThread currentThread]);if (listFolderResult) {NSArray<DBFILESMetadata *> *entries = listFolderResult.entries;for (DBFILESMetadata *entry in entries) {if ([entry isKindOfClass:[DBFILESFileMetadata class]]) {DBFILESFileMetadata *fileMetadata = (DBFILESFileMetadata *)entry;NSString *filePath = fileMetadata.pathDisplay;NSURL *fileOutputUrl = [outputUrl URLByAppendingPathComponent:fileMetadata.name];NSString *fileOutputPath = [fileOutputUrl path];NSLog(@"Downloading \"%@\" to \"%@\", filePath, fileOutputPath);NSString *downloadTaskKey = [NSString stringWithFormat:@"DownloadTask.%@", [NSUUID UUID].UUIDString];[self.shouldContinueLock lock];if (!_shouldContinue) {NSLog(@"No longer continuing...");[self.shouldContinueLock unlock];return;}DBDownloadUrlTask *downloadTask = [self downloadFile:filePath fileOutputUrl:fileOutputUrl downloadTaskKey:downloadTaskKey];[self.downloadUrlTasks setObject:downloadTask forKey:downloadTaskKey];[self.shouldContinueLock unlock];}else if ([entry isKindOfClass:[DBFILESFolderMetadata class]]) {DBFILESFolderMetadata *folderMetadata = (DBFILESFolderMetadata *)entry;NSURL *directoryOutputUrl = [outputUrl URLByAppendingPathComponent:folderMetadata.pathDisplay];NSString *directoryOutputPath = [directoryOutputUrl path];if (![_fileManager fileExistsAtPath:directoryOutputPath]) {NSError *error;[_fileManager createDirectoryAtPath:directoryOutputPath withIntermediateDirectories:@(YES) attributes:nil error:&error];if (error) {NSLog(@"Error creating directory: %@", error);}}[self downloadFolderHelper:[NSString stringWithFormat:@"%@/%@", inputPath, folderMetadata.name] outputUrl:directoryOutputUrl];} else if ([entry isKindOfClass:[DBFILESDeletedMetadata class]]) {continue;}}[self.tasksLock lock];[_downloadUrlTasks removeObjectForKey:listFolderTaskKey];[self.tasksLock unlock];} else {NSLog(@"Error listing folder \"%@\":", inputPath);if (routeError) {NSLog(@"RouteError: %@", routeError);}NSLog(@"Error: %@", error);}}];return listFolderTask;}-(DBDownloadUrlTask *)downloadFile:(NSString *)filePath fileOutputUrl:(NSURL *)fileOutputUrl downloadTaskKey:(NSString *)downloadTaskKey {DBDownloadUrlTask *downloadTask = [[_client.filesRoutes downloadUrl:filePath overwrite:@(YES) destination:fileOutputUrl]response:_responseQueue response:^(DBFILESFileMetadata *downloadResult, DBFILESDownloadError *routeError, DBError *error, NSURL *destination) {NSLog(@"Handling download response on: %@", [NSThread currentThread]);if (downloadResult) {NSLog(@"Successfully downloaded \"%@\" to \"%@\", downloadResult.pathDisplay, [destination path]);[self.tasksLock lock];[self.downloadUrlTasks removeObjectForKey:downloadTaskKey];[self.tasksLock unlock];} else {NSLog(@"Error downloading \"%@\" to \"%@\", filePath, [fileOutputUrl path]);if (routeError) {NSLog(@"RouteError: %@", routeError);}NSLog(@"Error: %@", error);}}];return downloadTask;}-(void)cancelDownload {[self.shouldContinueLock lock];self.shouldContinue = NO;[self.shouldContinueLock unlock];[self.tasksLock lock];[self cancelAndClearTasks];[self.tasksLock unlock];}- (void)cancelAndClearTasks {for (NSString *key in _rpcTasks) {DBRpcTask *task = _rpcTasks[key];[task cancel];NSLog(@"Canceled task: %@", @(task.task.taskIdentifier));}for (NSString *key in _downloadUrlTasks) {DBDownloadUrlTask *task = _downloadUrlTasks[key];[task cancel];NSLog(@"Canceled task: %@", @(task.task.taskIdentifier));}[_rpcTasks removeAllObjects];[_downloadUrlTasks removeAllObjects];}
About Dropbox API Support & Feedback
Find help with the Dropbox API from other developers.
The Dropbox Community team is active from Monday to Friday. We try to respond to you as soon as we can, usually within 2 hours.
If you need more help you can view your support options (expected response time for an email or ticket is 24 hours), or contact us on X, Facebook or Instagram.
For more info on available support options for your Dropbox plan, see this article.
If you found the answer to your question in this Community thread, please 'like' the post to say thanks and to let us know it was useful!