Поскольку я нахожу раздражающую проблему очень долгого первого времени загрузки для клавиатуры (даже с 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];
}