我正在使用针屏幕登录我的应用。引脚屏幕由四个标签和一个隐藏文本字段组成。当用户通过键盘输入文本时,我用符号更新标签。这很好,除了最后一个标签在登录开始之前没有得到实际更新,并且在登录过程完成时保持为空。
这些是代码的相关部分:
//an observer has been added elsewhere
- (void)textDidChange:(NSNotification *)notification
{
UITextField *field = [notification object];
if (field == inputField)
{
NSString *newText = field.text;
if ([newText length] <= pinLength) [self updatePINDisplay];
}
}
-(void)updatePINDisplay
{
if ([pinText length] > pinLength) return;
for (NSInteger ii = 0; ii < [pinText length]; ii++)
{
UILabel *label = [pinFields objectAtIndex:ii];
[label setText:@"x"];
}
for (NSInteger ii = [pinText length]; ii < pinLength; ii++)
{
UILabel *label = [pinFields objectAtIndex:ii];
[label setText:[NSString string]];
}
if ([pinText length] == pinLength) [self login];
}
问题出现是因为[self login]启动了在更新最后一个引脚标签之前发生的其他进程,因此在最后一个框仍为空时进行登录。
我通过替换
解决了这个问题[self login]
与
[self performSelector:@selector(login) withObject:nil afterDelay:0.1]
但我不喜欢任意时间延迟。我希望可能有一个委托方法,我可以用它来绘制标签后启动我的登录代码。类似的东西:
-(void)labelDidGetDrawn
欢迎任何其他(非黑客)解决方案: - )
谢谢!
答案 0 :(得分:0)
怎么样:
[label setNeedsDisplay:YES];
if ([pinText length] == pinLength) [self login];
答案 1 :(得分:0)
根据您的描述,听起来问题是第4项在[self login]
完成之后才会被绘制,这表明登录过程需要一些时间。在iOS中,绘图不会立即发生,这就是为什么只有在操作系统有机会更新显示之后才推迟登录的原因。
您在这里使用了一个合理的解决方案。另一个(可以说是一个黑客攻击)是让你的-[self login]
在一个单独的线程上产生登录,或者至少使用异步机制(例如NSURLConnection的异步模式,假设你正在发出网络请求) 。然后你的主线程将迅速将控制权返回到iOS,你的框将被绘制。
使用Grand Central Dispatch,你可以通过让-[self login]
将网络代码放在后台线程上来完成大部分工作,并在完成后让后台线程回调你的主线程。但是,如果要在登录过程中响应用户事件,这可能会导致一些问题。
如果可以,异步使用NSURLConnection
并设置委托以在操作完成时向您报告可能是最佳选择,因为它为您提供取消NSURLConnection
的操作在登录过程中,如果用户请求它。
答案 2 :(得分:0)
是的,该通知存在某种方式。标签将在运行循环的下一次迭代期间绘制。那么在下一个运行循环迭代结束时你的login
,例如使用performSelector:afterDelay:0
或者使用
dispatch_async (dispatch_get_main_queue (), ^{ [self login]; });
但是a)这取决于渲染与定时器和dispatch_queues的执行顺序。如果在计时器执行之前进行渲染,那么你已经完成了设置。
并且b)不要阻止主线程。尝试在后台线程/并发队列中执行登录,或者如果您正在使用,请在主线程上异步执行,例如NSURLConnection
。