UIRefreshControl进入前景时的错误

当我在View Controller中使用UIRefreshControl时,我注意到了一些小错误(但真的很烦人)。 当应用程序从后台返回时, UIRefreshControl已经被加载,看起来像这样:

正如你所看到的,我使用了一个隐藏在Facebook应用程序( AMScrollingNavBar )中的自定义导航控制器。 当我在UITableView重新加载数据时,一切恢复正常,并且只有在从后台返回后才显示此错误。

这是我用来在viewDidLoad初始化UIRefreshControl的代码:

 // Initializing generic refresh control self.refreshControl = [[UIRefreshControl alloc] init]; [self.refreshControl addTarget:self action:@selector(collectData) forControlEvents:UIControlEventValueChanged]; [self.tableView addSubview:self.refreshControl]; 

这是iOS7中的一个已知错误。 你可以看到它在苹果的邮件应用程序中重现。 我可以确认它还没有被修正为iOS7.1 beta 5 iOS8.0 beta 3 iOS 10.0.1。

首先,在https://bugreport.apple.com/打开一个错误报告。我的雷达号是rdar://14586451 ,它是rdar://14493713 (仍然打开)的副本。

build议的解决办法是在您的视图控制器中注册UIApplicationWillEnterForegroundNotification通知,并调用[self.refreshControl.superview sendSubviewToBack:self.refreshControl]; 通过使刷新控件出现在你的表格内容之后来稍微解决这个问题。

我在第二个屏幕截图中看到刷新控件显示在您的单元格下。 这可能是因为你已经设置了一个清晰的颜色作为你的细胞的背景。 将其设置为白色。

我find了一个解决这个bug的变种。 它也可能帮助你。 在我的应用程序中,切换到另一个选项卡并使用刷新控件返回到选项卡时,打破了该选项 – 控件在拖动时不再生成animation。

我不是在viewDidLoad中设置UIRefreshControl,而是在viewDidAppear中设置它,然后在viewDidDisappear中删除它。 这样它总是初始化新鲜,不会感到困惑。

正如在这个问题的上一个答案,我已经请求UIApplicationDidBecomeActiveNotification,以便刷新控制可以修复也当用户跳回应用程序。

 @implementation MYViewController { UIRefreshControl *refreshControl; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; /* Pull down to refresh. iOS bug: If we add this in viewDidLoad and let it * stay there for the lifetime of the view, the control will misbehave * after going to another view/tab and coming back (will not animate nicely * on drag). */ [self setupRefreshControl]; /* We'll want to be notified for didBecomeActive, to do the pull-down-to-refresh workaround when resuming. */ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupRefreshControl) name:UIApplicationDidBecomeActiveNotification object:nil]; } - (void)setupRefeshControl { if (refreshControl) [refreshControl removeFromSuperview]; refreshControl = [[UIRefreshControl alloc] init]; [refreshControl addTarget:self action:@selector(refreshPull:) forControlEvents:UIControlEventValueChanged]; [scrollView addSubview:refreshControl]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [refreshControl removeFromSuperview]; refreshControl = nil; /* We don't need notification for becoming active any more */ [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; } 

稍微不理想,但有效。

在桌面视图控制器上进行模态演示时,以及应用程序从后台返回时,似乎会发生此错误。

最简单的解决方法是在viewWillAppear(_:)调用endRefreshing() ,并在收到UIApplicationWillEnterForeground通知后调用。 您需要执行这两个操作,因为viewWillAppear(_:)在应用程序从后台返回时不会被调用。

endRefreshing()实例上调用endRefreshing()的效果似乎是将控件返回到视图层次结构中的正确位置,并确保它在后续刷新中继续正确animation。

请记得检查一下,您的刷新控件实际上不是令人耳目一新的。

在Swift中:

 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) endRefreshing() NotificationCenter.default.addObserver(self, selector: #selector(endRefreshing), name: Notification.Name.UIApplicationWillEnterForeground, object: nil) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: Notification.Name.UIApplicationWillEnterForeground, object: nil) } func endRefreshing(_ notification: Notification? = nil) { if refreshControl?.isRefreshing == false { refreshControl?.endRefreshing() } } 

在Xcode 7.0中针对iOS 8.0进行了testing,并在故事板中configuration了UITableViewController。