UITableView的异步加载

时间:2014-03-14 16:16:33

标签: ios uitableview

以下是代码,我使用printerArray = [SMPort searchPrinter];加载数据。这是一个昂贵的操作和锁定ui。有没有办法异步这样做,所以我可以显示一个加载指示器,什么时候显示数据?

//
//  SearchPrinterViewController.m
//  PHP POS
//
//  Created by Chris Muench on 3/12/14.
//  Copyright (c) 2014 PHP Point Of Sale. All rights reserved.
//


#import "PrintingViewController.h"
#import "StarIO/SMPort.h"
#import "PrinterFunctions.h"

@interface PrintingViewController ()

@end

@implementation PrintingViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    uitableview_printerList.dataSource = self;
    uitableview_printerList.delegate = self;

    //Expensive operation. Could take up to 3-5 seconds
    printerArray = [SMPort searchPrinter];
}

- (void)viewDidUnload
{    
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    return printerArray.count + 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }

    if (indexPath.row < printerArray.count)
    {
        PortInfo *port = [printerArray objectAtIndex:indexPath.row];
        cell.textLabel.text = port.modelName;
        NSString *detailText = [NSString stringWithFormat:@"%@(%@)", port.portName, port.macAddress];
        cell.detailTextLabel.text = detailText;
    }
    else if (indexPath.row == printerArray.count)
    {
        cell.textLabel.text = @"Back";
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row < printerArray.count)
    {
        PortInfo *portInfo = [printerArray objectAtIndex:indexPath.row];
        [PrinterFunctions PrintPHPPOSDocumentWithPortName:portInfo.portName textToPrint:self.textToPrint portSettings:@""];
    }

    [self dismissViewControllerAnimated:YES completion:nil];

}

@end

2 个答案:

答案 0 :(得分:2)

// This sends the fetching operation on the background
// You can put a loading indicator HERE BEFORE the dispatch.
// This sends the fetching operation on the background
[SVProgressHUD showWithStatus:@"Finding Printers" maskType:SVProgressHUDMaskTypeBlack];
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    printerArray = [SMPort searchPrinter];

    // Here you send tell the main thread to reload the table
    dispatch_async(dispatch_get_main_queue(), ^{
        [SVProgressHUD dismiss];
        [uitableview_printerList reloadData];
    });
});

当然还有很多其他解决方案,但对我而言,这似乎是最小的解决方案。

编辑: 我忘记了一件事:为了使printArray在块中可写,你必须在声明它时在前面添加关键字 __ block

编辑:我把最终的工作代码。我不需要为某些reaosn添加__block。

答案 1 :(得分:0)

您可以使用第二个NSOperationQueue或GCD(Grand Central Dispatch)。 GCD方法如上所述。这是NSOperation队列方法:

NSOperationQueue *printQueue = [[NSOperationQueue alloc] init];
[printQueue addOperationWithBlock:^{

  // Background work
  NSArray * array = [SMPort searchPrinter];

  // Update the UI (in the main queue)
  [[NSOperationQueue mainQueue] addOperationWithBlock:^{
     printerArray = [array copy];
     [uitableview_printerList reloadData];
  }];
}];

看一下这个视频:

https://developer.apple.com/videos/wwdc/2012/index.php?id=211

和本教程:

http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues