2013-07-29 41 views
21

Tôi đang sử dụng đoạn mã sau để tạo ra một UIRefreshControl:UIRefreshControl trên viewDidLoad

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

Nó hoạt động tuyệt vời. Nếu tôi điều hướng đến chế độ xem của mình, hãy kéo bảng, mã chạy và dữ liệu sẽ hiển thị.

Tuy nhiên, những gì tôi muốn làm là có chế độ xem trong trạng thái 'tải' ngay khi nó xuất hiện (theo cách đó người dùng biết điều gì đó đang diễn ra). Tôi đã thử thêm các mục sau:

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

Nhưng có vẻ như nó không hoạt động. Khi tôi điều hướng đến chế độ xem, nó trông giống như một chế độ xem thông thường (điều khiển làm mới không hiển thị), cộng với khi tôi cố gắng kéo điều khiển làm mới, nó không bao giờ tải xong.

Rõ ràng là tôi sẽ làm điều này sai. Bất kỳ đề xuất về cách tôi nên xử lý này?

+0

Nó phù hợp với tôi. Tôi làm những điều đúng đắn. Chỉ có hành động cho refreshControl mới có thuộc tính người gửi. Khi tôi vào màn hình, điều khiển làm mới không hiển thị nhưng nếu tôi kéo chế độ xem bảng xuống một chút, tôi có thể thấy điều khiển làm mới quay. – dasdom

Trả lời

59

Hãy thử điều này:

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

Hãy nhớ để gọi endRefreshing tại một số điểm!

EDIT để thêm mẫu làm việc đầy đủ: điều khiển xem

mẫu này, được xây dựng và chạy trong iOS6.1 như viewController gốc bắt đầu với UIRefreshControl đã xuất hiện và sinh động khi ứng dụng khởi chạy.

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 
+1

Điều này có phù hợp với bạn không? Tôi đã cố gắng nhưng nó vẫn không hiển thị bất cứ điều gì cho đến khi tôi trượt ngón tay của tôi trên bàn. – Kyle

+0

có, nó hoạt động trong dự án mẫu mà tôi đã thực hiện. – TomSwift

+2

Chỉ hoạt động nếu contentOffset được đặt trước khi gọi bắt đầuRefreshing –

0
- (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];  

    } 

Bạn không bao giờ đặt self.refreshControl

+1

anh ta đặt self.refreshControl trong viewDidLoad, điều đó rất tốt. – TomSwift

+0

@TomSwift viewWillAppear được gọi là –

+4

đầu tiên không quá nhiều. chế độ xem cần được tải trước khi có thể xuất hiện. xem: http: // stackoverflow.com/questions/5107604/can-somebody-explain-the-process-of-a-uiviewcontroller-birth-which-method-follo – TomSwift

3

lựa chọn khác là bắn một UIControlEventValueChanged trong viewDidAppear của bạn: để kích hoạt làm mới ban đầu.

15

Sửa đổi thủ công contentOffsetkhông an toàn và sai và có thể dẫn đến hành vi không mong muốn trong một số trường hợp. Giải pháp này hoạt động mà không cần chạm vào contentOffset ở tất cả:

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

Điều này không chính xác. Nó là hoàn toàn hợp lệ (và thường xuyên cần thiết) để sửa đổi bù đắp nội dung (ví dụ, để bù đắp nội dung theo chiều dài của hướng dẫn bố cục hàng đầu). –

+2

"Điều này không chính xác. Nó hoàn toàn hợp lệ". Thực sự không có tranh luận ở đó, đó chỉ là ý kiến ​​của bạn. Bạn cho rằng bạn là người duy nhất chạm vào 'contentOffset', trong khi bạn không chạm vào. Vấn đề là bạn phải ** đặt lại ** bù đắp nội dung khi làm mới - và bạn không thể biết giá trị chính xác cho việc đặt lại nếu các thành phần khác của 'UIKit' cũng có thể thay đổi độ lệch cùng một lúc. –

+0

Nói rằng "không an toàn và sai" là một ý kiến. Nói rằng nó là hợp lệ để sửa đổi nội dung bù đắp là không - trong thực tế, hướng dẫn lập trình xem cuộn của Apple đặc biệt đề cập đến thiết lập bù đắp nội dung. Ví dụ: để đưa hướng dẫn bố cục vào tài khoản, ứng dụng của bạn có thể cần phải đặt bù trừ theo cách thủ công. Làm điều này trong viewDidLayoutSubviews đảm bảo rằng mã của bạn nhận được lời cuối cùng trong nội dung bù đắp nội dung. –