在iOS 8.1下出现UIPopoverController之前的不可预知的延迟

在iOS 8.1下运行时,SDK 8.1会发生此问题,但在iOS 7下运行时不会发生此问题。仅适用于iPad。 问题出现在模拟器和硬件设备上。

下面的代码演示了一个视图控制器,它包含一行UITableView,并在其下面有一个UIButton。 点击button或在行上将popup一个popup窗口。 这在点击button时工作得很好,但是当点击tableview的行时,popover会出现一些延迟。 在我的testing中,第一次点击排行通常会出现的排名很less或根本没有延迟,但是第二次点击该排时,出现排行可能需要几秒钟的时间,而且在我点击其他地方之前通常不会出现风景。 但是,即使在第一次敲击时,延迟也会发生(特别是在硬件上进行testing时)。

我所显示的代码已经尽可能的被parsing了,同时保留了这个问题。 在我看来,UITableView在某种程度上是导致这种延迟发生的关键。

我知道一些UIPopoverController代码在iOS 8下不推荐使用。我尝试过在iOS 8中使用UIPopoverPresentationController,结果是一样的:Popover出现之前有时很长的延迟。 我还不是很熟悉这种新的方法,所以我可能会犯错误,但在任何情况下,可以通过将USE_TRADITIONAL_METHODmacros设置为0而不是1来testingiOS 8代码。

任何build议如何解决或绕过(虽然仍然使用tableview)将不胜感激。

#import "MyViewController.h" @interface MyViewController () @property (nonatomic) UIPopoverController* myPopoverController; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; // setup table view UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 500, 500) style:UITableViewStyleGrouped]; [self.view addSubview:tableView]; tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; tableView.dataSource = self; tableView.delegate = self; // setup button UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem]; [self.view addSubview:button]; button.frame = CGRectMake(20, 550, 100, 20); [button setTitle:@"Show popover" forState:UIControlStateNormal]; [button addTarget:self action:@selector(showPopover:) forControlEvents:UIControlEventTouchUpInside]; } - (IBAction)showPopover:(id)sender { UIView* senderView = (UIView*)sender; UIViewController* contentViewController = [[UIViewController alloc] init]; contentViewController.view.backgroundColor = [UIColor purpleColor]; #define USE_TRADITIONAL_METHOD 1 #if USE_TRADITIONAL_METHOD self.myPopoverController = [[UIPopoverController alloc] initWithContentViewController:contentViewController]; [self.myPopoverController presentPopoverFromRect:senderView.frame inView:senderView.superview permittedArrowDirections:UIPopoverArrowDirectionLeft animated:NO]; #else contentViewController.modalPresentationStyle = UIModalPresentationPopover; [self presentViewController:contentViewController animated:NO completion:^{ NSLog(@"Present completion"); // As expected, this is executed once the popover is actually displayed (which can take a while) }]; // do configuration *after* call to present, as explained in Apple documentation: UIPopoverPresentationController* popoverController = contentViewController.popoverPresentationController; popoverController.sourceRect = senderView.frame; popoverController.sourceView = senderView; popoverController.permittedArrowDirections = UIPopoverArrowDirectionLeft; #endif NSLog(@"Popover is visible: %d", self.myPopoverController.isPopoverVisible); // This shows "1" (visible) for USE_TRADITIONAL_METHOD, under both iOS 7 and iOS 8 } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 1; } -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; cell.textLabel.text = @"Show popover"; return cell; } #pragma mark - UITableViewDelegate -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self showPopover:[tableView cellForRowAtIndexPath:indexPath]]; } @end 

我发现在试图显示popup窗口之前取消select该行似乎解决了这个问题。 这可能是一个有用的解决方法,但我仍然在寻找更好的答案,因为这可能不健壮。

 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; // adding this line appears to fix the problem [self showPopover:[tableView cellForRowAtIndexPath:indexPath]]; } 

非常感谢那个伎俩。 我有一个TableView,当我点击一行时显示一个popup窗口。 我的popover只是拖延之后才显示出来,或者甚至需要双击才能显示出来。 通过添加指定的行([tableView deselectRowAtIndexPath:indexPath animated:NO]),popup窗口立即显示,无需再次双击。