29

首次启动 UIRefreshControl 时,文本偏移错误...稍后有时刷新文本根本不显示,只有刺可见

我不认为我在 iOS6 上遇到过这个问题……可能与 iOS7 有关

位于作为子项添加到 VC 的 UITableViewController 中,该 VC 驻留在模态呈现的 UINavigationController 中

- (void)viewDidLoad {

    [super viewDidLoad];

    [self setRefreshControlText:@"Getting registration data"];
    [self.refreshControl beginRefreshing];
}

- (void)setRefreshControlText:(NSString *)text {

    UIFont * font = [UIFont fontWithName:@"Helvetica-Light" size:10.0];
    NSDictionary *attributes = @{NSFontAttributeName:font, NSForegroundColorAttributeName : [UIColor blackColor]};
    self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attributes];

}

在此处输入图像描述

在此处输入图像描述

4

8 回答 8

39

这绝对是 iOS 7 的错误,但我还没有弄清楚究竟是什么原因造成的。它似乎与视图层次结构有关——将我的 UITableViewController 作为子视图添加到包装器视图控制器似乎一开始就为我修复了它,尽管该错误自 iOS 7 GM 以来又回来了。

在创建刷新视图后,将以下代码添加到您的 UITableViewController 似乎可以永久修复定位问题:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.refreshControl beginRefreshing];
    [self.refreshControl endRefreshing];
});
于 2013-10-01T21:17:57.313 回答
4

打电话endRefreshingviewWillAppear我:

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.refreshControl endRefreshing];
}

iOS7下有一个自定义UITableViewController里面UINavigationController

于 2014-01-04T22:24:44.520 回答
3

我有同样的问题,对我来说,layoutIfNeeded在设置属性标题后它可以工作:

- (void)setRefreshControlText:(NSString *)text
{
    UIColor *fg = [UIColor colorWithWhite:0.4 alpha:1.0];
    NSDictionary *attrsDictionary = @{NSForegroundColorAttributeName: fg};
    self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attrsDictionary];
    [self.refreshControl layoutIfNeeded];
}

Cédric 建议使用[self.refreshControl setNeedsLayout],但这不会强制立即更新视图,因此您必须使用layoutIfNeeded.

于 2014-06-04T14:24:10.453 回答
2

我终于找到了这方面的圣杯,它看起来在所有情况下都有效

注意:UIRefreshControl被添加到一个UITableViewController(注意,永远不要UIRefreshControl像子视图一样添加到普通的 UIVIewController's UITableView)(如果必须,最好UITableViewController作为子 VC添加到 a 中)UIViewController

注意:这也解决了问题,即 UIRefreshControl 在第一次刷新时不可见链接

添加给你.h

@interface MyViewController ()

@property (nonatomic, assign) BOOL refreshControlFixApplied;

- (void)beginRefreshing;
- (void)beginRefreshingWithText:(NSString *)text;
- (void)endRefreshing;
- (void)endRefreshingWithText:(NSString *)text;

@end

添加到你.m

////////////////////////////////////////////////////////////////////////
#pragma mark - UIRefreshControl Fix (peter@min60.com) https://stackoverflow.com/questions/19121276/uirefreshcontrol-incorrect-title-offset-during-first-run-and-sometimes-title-mis/
////////////////////////////////////////////////////////////////////////

- (void)beginRefreshingWithText:(NSString *)text {

    [self setRefreshControlText:text];
    [self beginRefreshing];

}

- (void)endRefreshingWithText:(NSString *)text {

    [self setRefreshControlText:text];
    [self.refreshControl endRefreshing];

}

- (void)beginRefreshing {

    if (self.refreshControl == nil) {
        return;
    }

    if (!self.refreshControlFixApplied) {

        dispatch_async(dispatch_get_main_queue(), ^{

            if ([self.refreshControl.attributedTitle length] == 0) {
                [self setRefreshControlText:@" "];
            }
            [self.refreshControl beginRefreshing];

            dispatch_async(dispatch_get_main_queue(), ^{

                [self.refreshControl endRefreshing];

                dispatch_async(dispatch_get_main_queue(), ^{

                    // set the title before calling beginRefreshing
                    if ([self.refreshControl.attributedTitle length] == 0) {
                        [self setRefreshControlText:@" "];
                    }
                    if (self.tableView.contentOffset.y == 0) {
                        self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
                    }
                    [self.refreshControl beginRefreshing];

                    self.refreshControlFixApplied = YES;

                });

            });

        });

    } else {

        if (self.tableView.contentOffset.y == 0) {
            self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
        }
        [self.refreshControl beginRefreshing];

    }

}

- (void)endRefreshing {

    if (self.refreshControl == nil) {
        return;
    }

    if (!self.refreshControlFixApplied) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self endRefreshing];
        });
    } else {
        if (self.tableView.contentOffset.y < 0) {
            self.tableView.contentOffset = CGPointMake(0, 0);
        }
        [self.refreshControl endRefreshing];

    }

}

- (void)setRefreshControlText:(NSString *)text {

    UIFont * font = [UIFont fontWithName:@"Helvetica-Light" size:10.0];
    NSDictionary *attributes = @{NSFontAttributeName : font, NSForegroundColorAttributeName : [UIColor colorWithHex:0x00B92E]};
    self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:text attributes:attributes];

}

仅使用方法

- (void)beginRefreshing;
- (void)beginRefreshingWithText:(NSString *)text;
- (void)endRefreshing;
- (void)endRefreshingWithText:(NSString *)text;
于 2014-01-22T14:11:52.637 回答
2

UIRefreshControl 似乎仍然在 IOS9.3 上被破坏,当您在 tableView 被下拉时更改属性标题。似乎可行的是继承 UIRefreshControl 并在(属性)标题更改后强制更新其布局。核心修复是触发对 tableView contentOffset 的更改(在布局微调器和文本子视图的 _update 方法中导致一些隐藏的魔法)并另外强制帧高度为其预期值,以确保背景颜色填充下拉区域。

@implementation MEIRefreshControl
{
    __weak UITableView* _tableView;
}

- (instancetype)initWithTableView:(UITableView*)tableView
{
    self = [super initWithFrame:CGRectZero];
    if (self)
    {
        _tableView = tableView;
    }

    return self;
}

@synthesize title = _title;

- (void)setTitle:(NSString *)title
{
    if (!PWEqualObjects(_title, title))
    {
        _title = title;
        self.attributedTitle = [[NSAttributedString alloc] initWithString:_title ? _title : @""];

        [self forceUpdateLayout];
    }
}

- (void)forceUpdateLayout
{
    CGPoint contentOffset = _tableView.contentOffset;
    _tableView.contentOffset = CGPointZero;
    _tableView.contentOffset = contentOffset;
    CGRect frame = self.frame;
    frame.size.height = -contentOffset.y;
    self.frame = frame;
}

@end
于 2016-05-09T15:47:55.690 回答
1

这是似乎可以解决所有问题的代码。许多其他涉及开始或结束刷新的情况会干扰控件的其他部分。

//This chunk of code is needed to fix an iOS 7 bug with UIRefreshControls
static BOOL refreshLoadedOnce = NO;
if (!refreshLoadedOnce) {
  __weak typeof(self) weakself = self;
  [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){
    self.tableView.contentOffset = CGPointMake(0, -weakself.refreshControl.frame.size.height);
  } completion:^(BOOL finished) {
    weakself.refreshControl.attributedTitle = self.refreshControl.attributedTitle;
    [weakself.refreshControl setNeedsUpdateConstraints];
    [weakself.refreshControl setNeedsLayout];
    refreshLoadedOnce = YES;
  }];
}
//End of bug fix
于 2014-05-12T05:58:13.340 回答
1

我有同样的问题,我确实通过在初始化刷新控件后直接设置带有空格字符串的属性文本来刷新控件来解决它

_refreshControl = [[UIRefreshControl alloc]init];
[_refreshControl setAttributedTitle:[[NSAttributedString alloc]initWithString:@" "]];

之后,将新的属性文本设置为刷新控件就没有任何问题了。

[[self refreshControl] setAttributedTitle:[[NSAttributedString alloc]initWithString:[NSString stringWithFormat:@"Последнее обновление: %@", [dateFormat stringFromDate:[_post dateUpdated]]]]];

更新

当我使用 attrsDictionary 时,我注意到这个问题又回来了:

此代码工作正常

NSAttributedString* attributedString = [[NSAttributedString alloc]initWithString:string];
[[self refreshControl] setAttributedTitle: attributedString];

这使得刷新控件的标题在视图加载后直接出现

NSAttributedString* attributedString = [[NSAttributedString alloc]initWithString:string attributes:attrsDictionary];
[[self refreshControl] setAttributedTitle: attributedString];

我还没有找到解决方案。

更新

终于找到解决办法了,refreshcontrol init set attributes string 后也带属性:attrsDictionary

NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObjects:
                                 [NSArray arrayWithObjects:[UIColor appDarkGray], [UIFont fontWithName:@"OpenSans-CondensedLight" size:14.0f], nil] forKeys:
                                 [NSArray arrayWithObjects:NSForegroundColorAttributeName, NSFontAttributeName, nil]];
[_refreshControl setAttributedTitle:[[NSAttributedString alloc]initWithString:@" " attributes:attrsDictionary]];

所以在那之后设置新的刷新控件的标题就没有问题了。

于 2015-10-13T14:32:01.810 回答
0

我的解决方案是在中设置文本viewDidAppear,无需调用

beginRefreshingendRefreshing在 mainQueue

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"d MMM, HH:mm"];
    NSString *lastUpdated = [NSString stringWithFormat:NSLocalizedString(@"refresh_last_updated", nil),[formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[[DatabaseController sharedInstance] getCurrentSettings].lastTimeStamp doubleValue]]]];
    UIFont *font = [UIFont fontWithName:FONT_LATO_LIGHT size:12.0f];
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:lastUpdated attributes:@{NSFontAttributeName:font}];

    _refreshControl.attributedTitle = attrString;
}
于 2015-04-23T13:45:42.577 回答