UIRefreshControl首次运行时标题偏移不正确,有时标题丢失

时间:2013-10-01 16:23:31

标签: cocoa-touch uitableview ios7 uirefreshcontrol

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

我认为iOS6没有这个问题......可能与iOS7有关

将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];

}

enter image description here

enter image description here

8 个答案:

答案 0 :(得分:39)

这绝对是一个iOS 7的bug,但我还没弄清楚究竟是什么导致了它。它似乎与视图层次结构有关 - 将我的UITableViewController作为子视图添加到包装器视图控制器似乎最初为我修复它,尽管自iOS 7 GM以来该错误已经恢复。

在创建刷新视图后,将以下代码添加到UITableViewController似乎可以解决定位问题:

dispatch_async(dispatch_get_main_queue(), ^{
    [self.refreshControl beginRefreshing];
    [self.refreshControl endRefreshing];
});

答案 1 :(得分:4)

endRefreshing下调用viewWillAppear为我做了这件事:

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

    [self.refreshControl endRefreshing];
}

在iOS7下,UITableViewController

中包含自定义UINavigationController

答案 2 :(得分:3)

我遇到了同样的问题,对我来说,在设置了attributesTitle之后它与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

答案 3 :(得分:2)

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

注意:UIRefreshControl已添加到UITableViewController(请注意,永远不要将UIRefreshControl添加为普通UIVIewController的UITableView的子视图(最好添加UITableViewController } {如果你必须的话} UIViewController中的子VC?

注意:这也解决了问题,UIRefreshControl在第一次刷新时不易变色link

添加给你.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;

答案 4 :(得分:2)

当下拉tableView时更改attributesTitle时,UOSefreshControl似乎仍然在IOS9.3上被破坏。似乎工作的是子类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

答案 5 :(得分: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

答案 6 :(得分: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];

这使得refreshControl的标题在加载视图后直接显示

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

我还没有找到解决方案。

<强>更新

终于找到解决方案,在refreshcontrol init之后设置属性字符串也带有属性: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]];

所以在那之后设置新的refreshcontrol的标题没有问题。

答案 7 :(得分:0)

我的解决方案是在viewDidAppear中设置文字,无需拨打电话

mainQueue上的

beginRefreshingendRefreshing

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