进入前台时出现UIRefreshControl错误

时间:2014-03-08 18:53:31

标签: ios objective-c uitableview uinavigationcontroller uirefreshcontrol

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

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

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

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

3 个答案:

答案 0 :(得分:8)

这是iOS7中的已知错误。您可以在Apple的邮件应用程序中看到它重现。我可以确认它已经修复了 iOS7.1 beta 5 iOS8.0 beta 3 iOS 10.0.1。

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

建议的修复方法是在视图控制器中注册UIApplicationWillEnterForegroundNotification个通知,并通过让刷新控件显示在表格内容后面来调用[self.refreshControl.superview sendSubviewToBack:self.refreshControl];来解决问题。

我在第二个屏幕截图中看到刷新控件显示在您的单元格下。这可能是因为您已将明确的颜色设置为单元格的背景。将其设置为白色。

答案 1 :(得分:7)

我找到了一个变种此错误的解决方法。它也可能对你有帮助。在我的应用程序中,切换到另一个选项卡并返回到带有刷新控件的选项卡打破了它 - 控件在拖动时不再动画。

我没有在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];
}

稍微不理想,但有效。

答案 2 :(得分:5)

当在表视图控制器上进行模式演示以及应用程序从后台返回时,似乎会出现此错误。

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

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

请记住检查您的刷新控件实际上是不是在刷新。

在斯威夫特:

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()
    }
}

使用在故事板中配置的UITableViewController在Xcode 7.0中测试,目标是iOS 8.0。