Клавиатура UITextField блокирует runloop во время загрузки?

Поскольку я нахожу раздражающую проблему очень долгого первого времени загрузки для клавиатуры (даже с iphone4S ios 5), я пытаюсь реализовать пользовательский UITextField, который показывает идентификатор UIActivityIndicator, если клавиатура слишком долго нагрузки. Тем не менее, я обнаружил, что UIActivityIndicator не может быть добавлен в супервизор при загрузке клавиатуры. Индикатор активности появляется слишком рано, если я устанавливаю более короткую задержку, или индикатор появляется слишком поздно, когда клавиатура появляется, когда я устанавливаю немного большую задержку (0,3 мс, хотя на самом деле занимает примерно 1 секунду, так как клавиатура загружается).

Я попытался настроить индикатор активности с помощью функции performSelector: withObject: afterDelay: inModes: в NSRunLoopCommonModes, но похоже, что загрузка клавиатуры блокирует этот режим. Я также пробовал использовать GCD, но, похоже, я столкнулся с той же проблемой, что и в настройке индикатора активности в той же диспетчерской очереди, что и загрузка и отображение клавиатуры. Как я могу добавить представление индикатора активности во время загрузки клавиатуры? Вот мой код:

@interface CustomTextField : UITextField {
    UIActivityIndicatorView *spinner;
    CGPoint spinnerCenter;
    BOOL shouldShowSpinner;    
}
@property (assign) UIActivityIndicatorView *spinner;
@property (assign) CGPoint spinnerCenter;
@property (assign) BOOL shouldShowSpinner;
- (void)stopSpinner;
@end


@implementation CustomTextField

@synthesize spinner;
@synthesize spinnerCenter;
@synthesize shouldShowSpinner;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.spinnerCenter = self.frame.origin;
        self.spinner = nil;
        shouldShowSpinner = NO;
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(stopSpinner) 
                                                     name:UIKeyboardDidShowNotification 
                                                   object:nil];
    }
    return self;
}

- (void)stopSpinner
{
    shouldShowSpinner = NO;
    if (spinner != nil) {
        [spinner removeFromSuperview];
        spinner = nil;
    }
}


- (void)loadSpinner
{
    if (shouldShowSpinner) {
        CGRect rect = CGRectMake(spinnerCenter.x - 15, spinnerCenter.y - 15, 30, 30);
        self.spinner = [[[UIActivityIndicatorView alloc] initWithFrame:rect] autorelease];
        [spinner startAnimating];
        [theSuperview addSubview:spinner];
    }
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if ([self pointInside:point withEvent:event] && self.hidden == NO && self.isEditing == NO) {
        shouldShowSpinner = YES;

        // the GCD approach, have to be stuck on current dispatch queue?
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 300000000), dispatch_get_current_queue(), ^{
            if (shouldShowSpinner) {
                CGRect rect = CGRectMake(spinnerCenter.x - 15, spinnerCenter.y - 15, 30, 30);
                self.spinner = [[[UIActivityIndicatorView alloc] initWithFrame:rect] autorelease];
                [spinner startAnimating];
                [theSuperview addSubview:spinner];
            }
        });

        // The NSRunLoopApproach, NSRunLoopCommonModes blocked by keyboard loading?
        [self performSelector:@selector(loadSpinner) 
                   withObject:nil 
                   afterDelay:0.3 
                      inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
    }
    return [super hitTest:point withEvent:event];
}