【问题标题】:UIRefreshControl on viewDidLoadviewDidLoad 上的 UIRefreshControl
【发布时间】:2013-07-29 15:18:51
【问题描述】:

我正在使用以下代码来创建 UIRefreshControl:

- (void) viewDidLoad
{
    [super viewDidLoad];

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

- (void) doLoad
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
            // Instead of sleeping, I do a webrequest here.
            [NSThread sleepForTimeInterval: 5];

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

效果很好。如果我导航到我的视图,拖动表格,代码运行并显示数据。

但是,我想做的是让视图一出现就处于“加载”状态(这样用户就知道正在发生某些事情)。我尝试添加以下内容:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [self.refreshControl beginRefreshing];
}

但它似乎不起作用。当我导航到视图时,它看起来像一个常规视图(刷新控件不可见),而且当我尝试拉动刷新控件时,它从未完成加载。

显然我的做法是错误的。关于我应该如何处理的任何建议?

【问题讨论】:

  • 它对我有用。我做同样的事情。只有 refreshControl 的操作具有 sender 属性。当我进入屏幕时,刷新控件不可见,但如果我将表格视图拉下一点,我可以看到旋转的刷新控件。

标签: ios uitableview uirefreshcontrol


【解决方案1】:

试试这个:

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

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

    // kick off your async refresh!
    [self doLoad];
}

记得在某个时候调用 endRefreshing!

编辑以添加完整的工作示例:

这个示例视图控制器,作为根视图控制器在 iOS6.1 中构建和运行,以 UIRefreshControl 开始,该 UIRefreshControl 在应用启动时已经可见并具有动画效果。

TSTableViewController.h

@interface TSTableViewController : UITableViewController
@end

TSTableViewController.m

#import "TSTableViewController.h"

@implementation TSTableViewController
{
    NSMutableArray*    _dataItems;
}

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.refreshControl = [UIRefreshControl new];

    [self.refreshControl addTarget: self
                            action: @selector( onRefresh: )
                  forControlEvents: UIControlEventValueChanged];
}

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

    self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);

    [self.refreshControl beginRefreshing];
    [self onRefresh: nil];
}

- (void) onRefresh: (id) sender
{
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){

        _dataItems = [NSMutableArray new];

        for ( int i = 0 ; i < arc4random() % 100 ; i++ )
        {
            CFUUIDRef uuid = CFUUIDCreate( NULL );

            [_dataItems addObject: CFBridgingRelease(CFUUIDCreateString( NULL, uuid)) ];

            CFRelease( uuid );
        }

        [self.refreshControl endRefreshing];

        [self.tableView reloadData];
    });
}

#pragma mark - Table view data source

- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
    return 1;
}

- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection: (NSInteger) section
{
    return _dataItems.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
                                                   reuseIdentifier: nil];

    cell.textLabel.text = [_dataItems objectAtIndex: indexPath.row];

    return cell;
}

@end

【讨论】:

  • 这对你有用吗?我一直在尝试,但在我用手指在桌子上滑动之前它仍然没有显示任何内容。
  • 只有在调用 beginRefreshing 之前设置了 contentOffset 时才有效
  • 调整 contentOffset 确实使控件可见,但对我来说,它不会旋转,即使我调用 beginRefreshing(在更改内容偏移之前或之后)。
【解决方案2】:

手动修改contentOffset不安全且错误的,并且在某些情况下可能会导致意外行为。此解决方案完全无需接触contentOffset

func showRefreshControl(show: Bool) {
    if show {
        refreshControl?.beginRefreshing()
        tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: true)
    } else {
        refreshControl?.endRefreshing()
    }
}

【讨论】:

  • 这是不正确的。修改内容偏移量(例如,将内容偏移顶部布局指南的长度)是完全有效的(并且通常是必要的)。
  • “这不正确。它完全有效”。真的没有争论,这只是你的意见。您假设您是唯一接触contentOffset 的人,而您不是。问题是您必须在刷新时重置内容偏移量 - 如果UIKit 的其他组件也可能在同一时间。
  • 说它“不安全和错误”是一种观点。说修改内容偏移有效是不行的——实际上苹果的滚动视图编程指南中特别提到了设置内容偏移。例如,为了考虑布局指南,您的应用程序可能需要手动设置偏移量。在 viewDidLayoutSubviews 中执行此操作可确保您的代码最终决定内容偏移应该是什么。
  • 我喜欢这种技术,因为它看起来比修改偏移更干净。我发现由于我的表是空的,初始滚动被忽略。不过使用tableView.scrollRectToVisible(CGRectMake(0, -1, 1, 1), animated: false) 可以。另外,如果在第一个动画中我再次拉动它,刷新控制高度在达到 119 时会无缘无故下降 20 点,然后继续,就好像什么都没发生一样。
【解决方案3】:

另一个选项是在您的 viewDidAppear: 中触发 UIControlEventValueChanged 以触发初始刷新。

【讨论】:

    【解决方案4】:
       - (void) viewDidAppear: (BOOL) animated
       {
              [super viewDidAppear: animated];
              UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
              [refreshControl addTarget:self action:@selector(doLoad) forControlEvents:UIControlEventValueChanged];
              self.refreshControl = refreshControl;
              [self.refreshControl beginRefreshing];    
    
       }
    

    你永远不会设置 self.refreshControl

    【讨论】:

    • 他在viewDidLoad中设置了self.refreshControl,这样就好了。
    • @TomSwift viewWillAppear 首先被调用
    • 没那么多。视图需要加载才能出现。见:stackoverflow.com/questions/5107604/…
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多