Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

MrFusion

macrumors 6502a
Original poster
Jun 8, 2005
613
0
West-Europe
Hi
I would like to get your feedback on best practices with opening, closing, saving UIDocuments.
I have a viewController that shows the content of an UIDocument and which allows the user to rename documents and create new ones.

UIDocument does everything via completionHandlers to avoid blocking the UI. But if I want to rename a document, I first have a) to close it, b) rename it (via NSFileManager), c) open the new document, d) reload the view.
Same with a new document: a) close old document, b) create new document, c) open new document, d) reload the view.

But that is when everything works fine. If something goes wrong, the stack of completion handlers just keeps getting deeper.

I understand it can't work the same way as NSDocument because of iCloud and network delays.
But this many levels of if statements just "smells" bad. So what's the best approach?

ViewController, after returning from an UIActionSheet:
Code:
	switch (buttonIndex)
	{
		case 0: //destructive
			//todo: delete current document and present new document
			break;
		case 1:
		{
                               [[MyCloudManager sharedCloudManager] renameDocument:[self currentDocument]
											  completionHandler:^(BOOL succes, id renamedDocument) {
												  if (succes)
												  {
													  [self setCurrentDocument:renamedDocument];//will open the renamed document
												  }
											  }];
		}
			break;
		case 2:
		{
			double delayInSeconds = 0.3;
			dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
			dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
				//todo: notify user that it's going to take awhile?
			});
			
			
			
			[[self currentDocument] closeWithCompletionHandler:^(BOOL success) {
				if (success)
				{
					[[MyCloudManager sharedCloudManager] newUntitledDocument:NSStringFromClass([[self currentDocument] class])
														   completionHandler:^(BOOL succes, id newDocument) {
															   if (success)
															   {
																   [self setCurrentDocument:newDocument];//will open the new document
															   }
															   else
															   {
																   [[self currentDocument] openWithCompletionHandler^(BOOL success) {
																	   if (!success)
																	   {
																		   //tell the user the old file couldn't be reopenend
																	   }
																   }];//reopen the old document
															   }
														   }];
				}
			}];




and in MyCloudManager
Code:
-(void) renameDocument:(id) document
	 completionHandler:(void(^)(BOOL succes, id renamedDocument)) completionHandler
{
	_currentDocument = document;
	_renameBlock = completionHandler;
	
	UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[document localizedName]
														message:NSLocalizedString(@"Enter new name",@"alert message: enter new name for current document")
													   delegate:self
											  cancelButtonTitle:NSLocalizedString(@"Cancel",@"cancel rename current document")
											  otherButtonTitles:NSLocalizedString(@"rename", @"rename current document"), nil];
	
	[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
	[alertView show];

}

-(void)      alertView:(UIAlertView *) alertView
  clickedButtonAtIndex:(NSInteger) buttonIndex
{
	if (buttonIndex == 1)
	{
		void (^moveBlock)(NSString *) = ^(NSString *name){
			NSURL *currentURL = [_currentDocument fileURL];
			NSURL *baseURL = [currentURL URLByDeletingLastPathComponent];
			NSURL *newURL = [[baseURL URLByAppendingPathComponent:name] URLByAppendingPathExtension:[currentURL pathExtension]];
			
			NSError *error;
			[[NSFileManager defaultManager] moveItemAtURL:currentURL
													toURL:newURL
													error:&error];
			id newDocument = [(UIDocument *)[[_currentDocument class] alloc] initWithFileURL:newURL];
			_renameBlock((error == nil),newDocument);
		};
		
		//todo: don't overwrite existing files
		//if (!([baseURL checkResourceIsReachableAndReturnError:nil] && ![newURL checkResourceIsReachableAndReturnError:nil]))
		
		NSString *newName = [[alertView textFieldAtIndex:0] text];
		if ([_currentDocument documentState] == UIDocumentStateClosed)
		{
			moveBlock(newName);
		}
		else if ([_currentDocument documentState] == UIDocumentStateNormal)
		{
			[_currentDocument closeWithCompletionHandler:^(BOOL success) {
				moveBlock(newName);
			}];
		}
	}
	else
	{
		_renameBlock(NO,nil);//user didn't rename document
	}
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.