在 CTCallCenter callEventHandler 中取消隐藏视图非常慢

发布于 2024-11-14 22:34:51 字数 1874 浏览 4 评论 0原文

在原始问题未得到解答后重新发布更简洁、更有针对性的问题。经过一天的研究后,还对问题有了更深入的了解:

在我的应用程序委托 (didFinishLaunching) 中,我在 CTCallCenter 上设置了一个 callEventHandler。 这个想法是,当 callState 更改时,我会使用 userInfo 字典发布通知 包含call.callState。在我看来,我注意到了这个通知,并且当 userInfo 字典包含值 CTCallDisconnected,我想取消隐藏视图。

我遇到的问题是,隐藏方面几乎始终持续约 7 秒。 其他一切都工作正常,我知道这一点是因为我在取消隐藏之前和之后 NSLog, 这些日志会立即显示,但该死的视图仍然滞后 7 秒。

这是我的代码:

appDidFinishLaunching:

self.callCenter = [[CTCallCenter alloc] init];
    self.callCenter.callEventHandler = ^(CTCall* call) {
        // anounce that we've had a state change in our call center
        NSDictionary *dict = [NSDictionary dictionaryWithObject:call.callState forKey:@"callState"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CTCallStateDidChange" object:self userInfo:dict];
    };

然后,当用户点击拨打电话号码的按钮时,我会监听此通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ctCallStateDidChange:) name:@"CTCallStateDidChange" object:nil];

然后,在 ctCallStateDidChange: 中,

- (void)ctCallStateDidChange:(NSNotification *)notification
{
   NSLog(@"121");
   NSString *callInfo = [[notification userInfo] objectForKey:@"callState"];
   if ([callInfo isEqualToString:CTCallStateDisconnected]) {
      NSLog(@"before show");
      [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
      NSLog(@"after show");
   }
}

我已将问题跟踪到上述代码示例中的 if 条件:

 if ([[userInfo valueForKey:@"userInfo"] valueForKey:@"callState"] == CTCallStateDisconnected) {

如果我只是替换:然后

if (1 == 1) {

视图立即出现!

问题是,那些 NSLog 语句会立即记录,但视图是 落后是显而易见的。这种情况怎么可能只导致部分阻塞 立即执行,其余的等待〜7秒?

谢谢!

Reposting with more concise and focused question after original question went unanswered. Also adding more insight into the problem after another day of research:

In my app delegate (didFinishLaunching), I set up a callEventHandler on CTCallCenter.
The idea is that when a callState changes, I post a notification with a userInfo dict
containing the call.callState. In my view, I observe this notification, and when the
userInfo dict contains a value of CTCallDisconnected, I want to unhide a view.

The problem I'm having is that the unhiding aspect is taking, almost consistenly, ~ 7 seconds.
Everything else is working fine, and I know this because I NSLog before and after the unhiding,
and those logs appear immediately, but the darned view still lags for 7 seconds.

Here's my code:

appDidFinishLaunching:

self.callCenter = [[CTCallCenter alloc] init];
    self.callCenter.callEventHandler = ^(CTCall* call) {
        // anounce that we've had a state change in our call center
        NSDictionary *dict = [NSDictionary dictionaryWithObject:call.callState forKey:@"callState"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CTCallStateDidChange" object:self userInfo:dict];
    };

I then listen for this notification when a user taps a button that dials a phone number:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ctCallStateDidChange:) name:@"CTCallStateDidChange" object:nil];

Then, in ctCallStateDidChange:

- (void)ctCallStateDidChange:(NSNotification *)notification
{
   NSLog(@"121");
   NSString *callInfo = [[notification userInfo] objectForKey:@"callState"];
   if ([callInfo isEqualToString:CTCallStateDisconnected]) {
      NSLog(@"before show");
      [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
      NSLog(@"after show");
   }
}

I've tracked the problem down to the if condition in the above code sample:

 if ([[userInfo valueForKey:@"userInfo"] valueForKey:@"callState"] == CTCallStateDisconnected) {

If I simply replace that with:

if (1 == 1) {

Then the view appears immediately!

The thing is, those NSLog statements are logging immediately, but the view is
lagging in it's unhiding. How could that condition cause only part of it's block
to execute immediately, and the rest to wait ~ 7 seconds?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

闻呓 2024-11-21 22:34:51

尝试将代码更改为:

- (void)ctCallStateDidChange:(NSNotification *)notification
{
   NSLog(@"121");
   NSString *callInfo = [[notification userInfo] objectForKey:@"callState"];
   if ([callInfo isEqualToString:CTCallStateDisconnected]) {
      NSLog(@"before show");
      [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
      NSLog(@"after show");
   }
}

注意:

  • 参数是 NSNotification,而不是 NSDictionary
  • 我不会将字符串与 == 进行比较,
  • 无需投射视图以更改 hidden 属性
  • 使用 NO 而不是 false

更新:有一个想法:你可以尝试吗请在 NSLog 之间添加以下内容?

dispatch_async(dispatch_get_main_queue(), ^{
   [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
});

阅读 CTCallCenter 文档,似乎 callEventHandler 是在“默认优先级全局调度队列”上调度的,这不是所有 UI 操作发生的主队列。

Try changing your code to this:

- (void)ctCallStateDidChange:(NSNotification *)notification
{
   NSLog(@"121");
   NSString *callInfo = [[notification userInfo] objectForKey:@"callState"];
   if ([callInfo isEqualToString:CTCallStateDisconnected]) {
      NSLog(@"before show");
      [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
      NSLog(@"after show");
   }
}

Note:

  • The parameter is an NSNotification, not an NSDictionary
  • I would not compare strings with ==
  • No need to cast the view to change the hidden property
  • Use NO instead of false

Update: Got an idea: Could you try the following, please, in between the NSLogs?

dispatch_async(dispatch_get_main_queue(), ^{
   [self.view viewWithTag:kNONEMERGENCYCALLSAVEDTOLOG_TAG].hidden = NO;
});

Reading the CTCallCenter doc, it seems the callEventHandler is dispatched on "the default priority global dispatch queue", which is not the main queue where all the UI stuff happens.

柒夜笙歌凉 2024-11-21 22:34:51

看起来你的隐藏代码没有问题。如果我是你,我会在调用结束后将所有代码注释掉,然后一一取消注释,看看问题出在哪里。

Looks like there is no problem with your hidden code. If I were you, I would comment out all the code after the call ends, and uncomment them one by one to see what is the problem.

回忆追雨的时光 2024-11-21 22:34:51

嗯...更改隐藏属性后尝试调用 [yourViewController.view setNeedsDisplay] 。或者避免隐藏,改用 alpha 或 addSubview: 和 removeFromSuperview 方法。

Hm... try to call [yourViewController.view setNeedsDisplay] after you change hidden property. Or avoid hidden, use alpha or addSubview: and removeFromSuperview methods instead.

顾冷 2024-11-21 22:34:51

djibouti33,

当用户点击拨打电话号码的按钮时,您将这句话放在 WillResignActive 函数上的什么位置?

这句话--> [[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(ctCallStateDidChange:) 名称:@"CTCallStateDidChange" 对象:nil];

谢谢你的宝贵时间,

威利。

djibouti33,

Where you put this sentence to listen when a user taps a button that dials a phone number?on WillResignActive function?

this sentence --> [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ctCallStateDidChange:) name:@"CTCallStateDidChange" object:nil];

Thanks for your time,

Willy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文