【问题标题】:UIRefreshControl bug when entering foreground进入前台时的 UIRefreshControl 错误
【发布时间】:2014-04-11 23:42:48
【问题描述】:

当我在视图控制器中使用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];

【问题讨论】:

    标签: ios objective-c uitableview uinavigationcontroller uirefreshcontrol


    【解决方案1】:

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

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

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

    记得检查你的刷新控件实际上是不是在刷新。

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

    在面向 iOS 8.0 的 Xcode 7.0 中测试,并在情节提要中配置了 UITableViewController。

    【讨论】:

    • 嗨,我试过这个,但是当我的应用程序从后台返回时崩溃了。它找不到选择器。 “无法识别的选择器发送到实例”。只有当我从后台返回时,否则它工作正常:/
    • 没有帮助,但我删除了 notificationCenter 调用,它似乎工作。还没有遇到过这个错误,那是 3 天前的事了。希望它有效:)
    • “模态窗口” - 您在这里没有正确使用“窗口”一词。
    【解决方案2】:

    这是 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]; 通过让刷新控件出现在您的表格内容后面来稍微解决这个问题。

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

    【讨论】:

    • 很遗憾,它仍然没有按应有的方式制作动画。你的回答至少帮助我隐藏了这个可怕的观点!在这种情况下,我将再次使用自定义的下拉刷新进行协调!
    • UIRefreshControl 还有很多其他的错误。我想我为这门课写了大约 10 个错误报告。
    • 2016 年 4 月,iOS 9.2 - 仍然冻结。
    【解决方案3】:

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

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

    稍微次优,但有效。

    【讨论】:

    • 在 iOS9/XCode 7.2 中遇到了另一个变化:在 UINavigationController 管理的、包含 UICollectionView 的子类 UIViewController 上,推送/弹出到导航堆栈同时还调用 setNavigationBarHidden(_:animated:) 会导致在集合视图的内容偏移更改 1pt 后立即出现刷新控件。此外,刷新控件处于完全不透明状态并且没有动画。但是在 viewDidAppear 中有一个类似于你的函数可以解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 2015-10-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2014-02-15
    相关资源
    最近更新 更多