web-dev-qa-db-ja.com

UIRefreshControlの初回実行時のタイトルオフセットが正しくなく、タイトルが欠落している場合があります

UIRefreshControlの最初の起動によって、テキストが誤ってオフセットされます...後で、更新テキストがまったく表示されず、とげのあるものだけが表示されることがあります

IOS6でこの問題が発生したとは思わない... iOS7に関連している可能性があります

モーダルで提示されたUINavigationControllerに存在するVCに子として追加されたUITableViewControllerにあります

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

29
Peter Lapisu

これは間違いなくiOS7のバグですが、原因は正確にはわかりません。ビュー階層と関係があるようです。UITableViewControllerを子ビューとしてラッパービューコントローラーに追加すると、最初は修正されたように見えましたが、バグはiOS 7GM以降に戻っています。

更新ビューを作成した後、UITableViewControllerに次のコードを追加すると、配置の問題が完全に修正されるようです。

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

endRefreshingの下でviewWillAppearを呼び出すと、次のようになります。

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

    [self.refreshControl endRefreshing];
}

IOS7では、UITableViewController内にカスタムUINavigationControllerがあります

4
Edgar

私も同じ問題を抱えていましたが、attributedTitleを設定した後、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

TableViewがプルダウンされているときにattributedTitleを変更すると、IOS9.3ではUIRefreshControlがまだ壊れているようです。うまくいくように見えるのは、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
2
berbie

私はついにこれに聖杯を見つけました、それはすべての場合に機能しているように見えます

注:UIRefreshControlUITableViewControllerに追加されます(注:通常のUIVIewControllerのUIRefreshControlのサブビューと同じようにUITableViewを追加しないでください)(UITableViewController子としてVC必要に応じて、UIViewController内)

注:これにより問題も修正され、UIRefreshControlが最初の更新時に表示されないことに注意してくださいlink

あなたに追加.h

@interface MyViewController ()

@property (nonatomic, assign) BOOL refreshControlFixApplied;

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

@end

あなたに追加します。

////////////////////////////////////////////////////////////////////////
#pragma mark - UIRefreshControl Fix ([email protected]) 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;
2
Peter Lapisu

これは、すべての問題を修正しているように見えるコードです。コントロールの他の部分に干渉するリフレッシュの開始または終了を伴う他の多く。

//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
1
Brett

私は同じ問題を抱えていました、私はスペース文字列を持つ属性テキストをinitリフレッシュコントロールの直後にリフレッシュコントロールに設定することによってそれを解決しました

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

その後、新しい属性テキストを更新コントロールに設定しても問題はありませんでした。

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

[〜#〜] update [〜#〜]

AttrsDictionaryを使用すると、問題が再発することに気づきました。

このコードは正常に機能します

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

これにより、ビューが読み込まれた直後にrefreshControlのタイトルが表示されます

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

私はまだ解決策を見つけられませんでした。

[〜#〜] update [〜#〜]

ついに解決策が見つかりました。refreshcontrolinitが属性付き文字列を属性付きで設定した後、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のタイトルを設定するのに問題はありません。

1
Maxime Ashurov

私にとっての解決策は、viewDidAppearにテキストを設定することでした。呼び出す必要はありません

mainQueueのbeginRefreshingまたはendRefreshing

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