Поскольку я нахожу раздражающую проблему очень долгого времени первой загрузки клавиатуры (даже с iphone4S ios 5), я пытаюсь реализовать пользовательский UITextField, который показывает UIActivityIndicator, если клавиатура слишком долго нагрузки. Однако я обнаружил, что UIActivityIndicator не может быть добавлен в суперпредставление во время загрузки клавиатуры. Либо индикатор активности появляется слишком рано, если я установил более короткую задержку, либо индикатор появляется слишком поздно, так как появляется клавиатура, когда я установил немного более длительную задержку (0,3 мс, хотя в действительности это занимает 1+ секунды , как клавиатура загружается).
Я пытался настроить индикатор активности с помощью executeSelector: 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];
}