Uirefreshcontrol() in iOS 11 Glitchy Effect

UIRefreshControl() in iOS 11 Glitchy effect

For me self.extendedLayoutIncludesOpaqueBars = YES fixed the issue.

UITableViewController refreshControl is glitchy when UITableViewController frame.height is small

I managed to recreate your issue exactly by accident and managed to fix it, but at the cost of having no margins at all.

The jumping seems to happen if you use margin based constraints or any kind of margin for your container view. If you remove the margin relative part of the constraints, the jumping disappears.

Very strange, but seems to be the issue. As soon as I add any margin relative constraint for the container, the issue returns. Removing it and the display goes back to smooth scrolling.

This would seem to be a bug and I think you will need to raise a bug report with Apple.

Update:

Looking again, the issue seems to appear as soon as the container view is not the full width of the screen. Adding any sort of margin to the container view (via layout relative to margin or by setting a non zero offset on a constraint) results in the jumpy behavior.

Update:

Something would appear to be fundamentally broken with UITableView scrolling inside a container view which has any kind of margin. If you override the scrolling delegate, the content offset/bounds of the scroll view are being changed at the moment the refresh is about to trigger. Here is some debug showing the issue

Start pulling down:

Scroll bounds = {{0, -127.33333333333333}, {374, 423}}
Scroll pos = [0.000000,-127.333333]
Scroll bounds = {{0, -127.66666666666667}, {374, 423}}
Scroll pos = [0.000000,-127.666667]
Scroll bounds = {{0, -128.33333333333334}, {374, 423}}
Scroll pos = [0.000000,-128.333333]

Ok before here ------->

Activity spinner becomes fully populated. Jump in scroll position upwards.

Scroll bounds = {{0, -104}, {374, 423}}
Scroll pos = [0.000000,-104.000000]

Scroll position corrects itself

Scroll bounds = {{0, -128.33333333333334}, {374, 423}}
Scroll pos = [0.000000,-128.333333]
Scroll position jumps the other direction by the same amount
Scroll bounds = {{0, -151.33333333333334}, {374, 423}}
Scroll pos = [0.000000,-151.333333]

Value changed target action fires. Bounds seem to reset (think 44 is height of refresh control

Scroll bounds = {{0, -44}, {374, 423}}
Scroll pos = [0.000000,-44.000000]
Corrects back
Scroll bounds = {{0, -151.33333333333334}, {374, 423}}
Scroll pos = [0.000000,-151.333333]
Fully corrects to the right scroll position by jumping back.

Ok after here ------>

Scroll bounds = {{0, -128.66666666666666}, {374, 423}}
Scroll pos = [0.000000,-128.666667]
Scroll bounds = {{0, -129}, {374, 423}}
Scroll pos = [0.000000,-129.000000]
Scroll bounds = {{0, -129.33333333333334}, {374, 423}}
Scroll pos = [0.000000,-129.333333]
Scroll bounds = {{0, -129.66666666666666}, {374, 423}}
Scroll pos = [0.000000,-129.666667]
Scroll bounds = {{0, -130}, {374, 423}}

Conclusion

There seems to be no easy way I can find to work around this. I tried creating my own table view controller and the jumping goes away but is replaced by a different effect: that being that when you scroll down the top cell disappears, then reappears. I imagine it relates to the same internal issue, just being expressed differently.

Unfortunatley looks like you might have to put up with the effect or go for no margin. I would raise a bug report with Apple.

Only alternative option would be to create the margins in your UITableViewCells. You could make the cell content view have a clear background and introduce a left and right margin to your cells using an internal container view for your cell content. I think that may be you best chance.

And Finally...

Not to be defeated, you can apply a scaling transform to the navigation controller for the table view to create a margin doing the following in your table view controller:

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)

// Add a scaling transform to the whole embedded controller view.
self.navigationController!.view.transform=CGAffineTransformMakeScale(0.9, 0.9);
}

This makes the view for the embedded controller appear 90% smaller so it has a margin around the border. Change the scale to to change the border size.

Not ideal, but works perfectly with no jump scrolling and has a border. It also leaves you totally free to use rounded corners etc as the whole content is scaled.

How to add refresh control to collection view large titles navigation bar in iOS 11?

As of iOS 10, UITableView and UICollectionView has refreshControl property.

So, instead of:

tableView.addSubview(refreshControl)

you do:

tableView.refreshControl = refreshControl

and this should work for new big headers in iOS 11.

UIRefreshControl not showing in landscape when in a navigation controller with large titles

We fixed this by recreating the refresh control on every rotation. It's called in viewDidLoad() too.

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)

if traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass {
tableView.refreshControl = UIRefreshControl() // !!!
tableView.refreshControl.addTarget(self, action: #selector(didPullToRefresh), for: .valueChanged)
}
}

@objc func didPullToRefresh() {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in
tableView.refreshControl.endRefreshing()
}
// ...
}

iOS 11 scroll to top when using large titles doesn't work properly

Okay so I found why the problem occurs, but not how to fix it in that exact scenario.

If you're using large titles and a UITableViewController with the navigation bar translucency set to off the problem will occur.
When you turn translucent back on the problem goes away.

If you're using a TableView in a normal UIViewController the problem always occurs.

Edit

Turns out setting "extendedLayoutIncludesOpaqueBars = true" fixes the problem if you're using a translucent navigation bar!

Similar question: UIRefreshControl() in iOS 11 Glitchy effect

UIRefreshControl without UITableViewController

On a hunch, and based on DrummerB's inspiration, I tried simply adding a UIRefreshControl instance as a subview to my UITableView. And it magically just works!

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:@selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];

This adds a UIRefreshControl above your table view and works as expected without having to use a UITableViewController :)


EDIT: This above still works but as a few have pointed out, there is a slight "stutter" when adding the UIRefreshControl in this manner. A solution to that is to instantiate a UITableViewController, and then setting your UIRefreshControl and UITableView to that, i.e.:

UITableViewController *tableViewController = [[UITableViewController alloc] init];
tableViewController.tableView = self.myTableView;

self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:@selector(getConnections) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = self.refreshControl;


Related Topics



Leave a reply



Submit