Mac / iPhone App Development
Home of a Small Time Developer

UIKit Modal Prompt

in order to not lock the ui iVersion runs it’s svn commands in a seperate threads. The promblem arises when one of thses threads needs to prompt for a value e.g. a username / password. Firstly UIKit does not provide a modal alert view and secondly UIKit should only be called from the mainThread.

First we create a new class which has a view which will be loaded from a nib, a thread condition to lock the calling thread and two NSString fields to store the result and the string of the button which was clicked.

@interface MessagePrompt : NSObject
{
 
UIView * view;
NSCondition * promptCondition;
NSString * clickedButton Text;
NSString * result;
{
@end

Our new prompt method can be called from the thread which needs to be locked, it will subsequently call UIKit on the main thread.

+(id)newPrompt:(MessagePrompt*)prompt
{
 
     if ([NSThread currentThread] == [NSThread mainThread])
    {
          printf("Should not be called by Main thread\n");
          return nil;
    }
 
     prompt.promptCondition = [[[NSCondition alloc] init] autorelease];
 
    [prompt performSelectorOnMainThread:@selector(prompt:) withObject:view waitUntilDone:NO];
    [prompt.promptCondition wait];
 
    return prompt;
}

This method is called by +(id)NewPrompt and displays a prompt in our window. It also adds targets to each UIButton to receive user actions.

-(void)prompt:(UIView*)inView
{
     NSArray * nib = [[NSBundle mainBundle] loadNibNamed:@"MyPromptView" owner:self options:nil];
     inView = [nib objectAtIndex:0];	
 
     NSArray * subviews = [self.view subviews];
     for (UIView * cview in subviews)
    {
          if ([cview isKindOfClass:[UIButton class]])
          {
               UIButton * button = (UIButton*)cview;
                [button addTarget:self action:@selector(clicked:) forControlEvents:UIControlEventTouchDown];
          }
    }
 
    [inView.superview addSubview:view];
}

This is called when a user clicks a button, it finds the value field and retreives and stores the value in self.message. The prompt condition is then signalled which causes the calling thread to continue running.

-(IBAction)clicked:(UIButton*)sender
{
     self.clickedButton = sender.currentTitle;
 
     UITextView * text = [iVersionAppDelegate findSubViewOfKind:self.view class:[UITextView class]];
     if (text)
    {
         self.message = text.text;
    }
 
    [self.view removeFromSuperview];
     self.view = nil;
 
    [promptCondition signal];
}
 
@end

Usage

/* Called when svn requires a log message */
svn_error_t *
iversion_svn_cl__get_log_message(const char **log_msg,
const char **tmp_file,
const apr_array_header_t *commit_items,
void *baton,
apr_pool_t *pool)
{
 
CommitLogMessagePrompt * prompt = [CommitLogMessagePrompt newPrompt];
 
    /* Clicked Continue */
     if ([prompt.clickedButton isEqualToString:@"Continue"])
    {
        *log_msg = [prompt.message UTF8String];
         return SVN_NO_ERROR;
    }
 
     return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Delete Cancelled"));
}
  • Share/Bookmark

Leave a Reply