IOS study note 13-UITableView package drop-down-upload-asynchronous image loading

Source: Internet
Author: User

 


Anyone who has worked on mobile development knows that list controls are one of the most commonly used controls. The list control in iOS is UITableView. In fact, Apple developers are well-designed for UITableView (easy to use and highly scalable ).

However, you can still feel a little complicated about displaying mobile-end system software with a single logic (maybe programmers are naturally a bit lazy ).

Let's see where it is complicated. First, it is often used too frequently; second, it is usually not just to present the data, it will generally follow the pull-down refresh, load more functions, of course, it is usually necessary to deal with the network to download data and images. Third, the MVC mode is the usual mode for ios development, followed by the implementation of a lot of protocols (whether you write it again or not, copy it. It seems boring to do this ).

With this in mind, we have encapsulated the common usage modes of UITableView today. Specifically, we have done the following:

1. embedded with the drop-down refresh (EGORefreshTableHeaderView), loading more (LoadMoreTableFooterView)

2. the built-in UITableViewDataSource and UITableViewDelegate protocols are usually required. The self-implemented logic is open to the customer's code in the form of blocks.

3. built-in implementation of the callback protocol for the two components mentioned in 1. Same as above, the self-implemented logic is open to the outside in the form of blocks.

4. The UIScrollViewDelegate protocol required for interaction between EGORefreshTableHeaderView, LoadMoreTableFooterView and UITableView is built in.

5. built-in asynchronous image download (optional)

 

You can go to my Github to view the source code. ELTableViewController is the first letter of EGORefreshTableHeaderView and LoadMoreTableFooterView.

This Code contains a sample program and three essential components:

1. EGORefreshTableHeaderView

2. LoadMoreTableFooterView (modified version, the original version cannot adapt to any size height)

3. The IconDownLoader (IconDownLoader) provided by Apple for asynchronous download of images in UITableView is only applicable to downloading user portraits similar to those in social networks. It is not recommended to use it to download those large images, because it is not even cached (SDImage is recommended if the image is large)

 

Code explanation
It has built in to implement these protocols, so you do not need to set and implement it when using it.

 

[Cpp]
@ Interface ELTableViewController: UIViewController
<
UITableViewDelegate,
UITableViewDataSource,
EGORefreshTableHeaderDelegate,
LoadMoreTableFooterDelegate,
IconDownloaderDelegate
>

 

For the ever-changing business logic, all blocks to be implemented are provided here:

[Cpp]
// Blocks for UITableView delegate
Typedef UITableViewCell * (^ cellForRowAtIndexPathDelegate) (UITableView *, NSIndexPath *);
Typedef CGFloat (^ heightForRowAtIndexPathDelegate) (UITableView *, NSIndexPath *);
Typedef void (^ didSelectRowAtIndexPathDelegate) (UITableView *, NSIndexPath *);
 
// Blocks for refresh and load more
Typedef void (^ refreshperformancefunc) (void );
Typedef void (^ loadMoreDataSourceFunc) (void );
 
Typedef void (^ refreshperformancecompleted) (void );
Typedef void (^ loadmoreperformancecompleted) (void );
// Use to load image (async)
Typedef void (^ loadImagesForVisiableRowsFunc) (void );
Typedef void (^ appImageDownloadCompleted) (NSIndexPath *);

 


They are made public in the form of attributes:

[Cpp]
// Property for blocks
@ Property (nonatomic, copy) cellForRowAtIndexPathDelegate;
@ Property (nonatomic, copy) heightForRowAtIndexPathDelegate;
@ Property (nonatomic, copy) didSelectRowAtIndexPathDelegate;
 
@ Property (nonatomic, copy) loadMoreDataSourceFunc;
@ Property (nonatomic, copy) refreshperformancefunc;
@ Property (nonatomic, copy) refreshperformancecompleted;
@ Property (nonatomic, copy) loadMoreDataSourceCompleted;
 
@ Property (nonatomic, copy) loadImagesForVisiableRowsFunc;
@ Property (nonatomic, copy) appImageDownloadCompleted;

The functions such as loading more, refresh down, and asynchronous image loading are optional. They exist as components. For example, when instantiating the controller, you can set whether the top-up and drop-down functions are available. For image downloading, as long as you do not implement the corresponding block, it will not impose additional burden on you.


[Cpp]
-(Id) initWithRefreshHeaderViewEnabled :( BOOL) enableRefreshHeaderView
AndLoadMoreFooterViewEnabled :( BOOL) enableLoadMoreFooterView;
 
-(Id) initWithRefreshHeaderViewEnabled :( BOOL) enableRefreshHeaderView
AndLoadMoreFooterViewEnabled :( BOOL) enableLoadMoreFooterView
AndTableViewFrame :( CGRect) frame;

[Cpp]
# Pragma mark-UITableView Delegate-
-(NSInteger) tableView :( UITableView *) tableView numberOfRowsInSection :( NSInteger) section {
If (nil = self. dataSource ){
Return 0;
}

Return [self. dataSource count];
}
 
-(UITableViewCell *) tableView :( UITableView *) tableView cellForRowAtIndexPath :( NSIndexPath *) indexPath {
If (! Self. cellForRowAtIndexPathDelegate ){
@ Throw [NSException exceptionWithName: @ "Framework Error"
Reason: @ "Must be setting cellForRowAtIndexPathBlock for UITableView" userInfo: nil];
}
Return self. cellForRowAtIndexPathDelegate (tableView, indexPath );
}
 
-(CGFloat) tableView :( UITableView *) tableView heightForRowAtIndexPath :( NSIndexPath *) indexPath {
If (! Self. heightForRowAtIndexPathDelegate ){
@ Throw [NSException exceptionWithName: @ "Framework Error"
Reason: @ "Must be setting heightForRowAtIndexPathDelegate for UITableView" userInfo: nil];
}
Return self. heightForRowAtIndexPathDelegate (tableView, indexPath );
}
 
-(Void) tableView :( UITableView *) tableView didSelectRowAtIndexPath :( NSIndexPath *) indexPath {
If (self. didSelectRowAtIndexPathDelegate ){
Self. didSelectRowAtIndexPathDelegate (tableView, indexPath );
}
}
 
# Pragma mark-LoadMoreTableFooterDelegate Methods-
-(Void) loadMoreTableFooterDidTriggerRefresh :( LoadMoreTableFooterView *) view {
If (self. loadmoreperformancefunc & self. loadmoreperformancecompleted ){
Self. loadmoreperformancefunc ();

Double delayInSeconds = 3.0;
Dispatch_time_t popTime = dispatch_time (DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC );
Dispatch_after (popTime, dispatch_get_main_queue (),
Self. loadmoreperformancecompleted );
}
}
 
-(BOOL) loadmoretablefooterperformanceisloading :( LoadMoreTableFooterView *) view {
Return self. isLoadingMore;
}
 
# Pragma mark-EGORefreshTableHeaderDelegate Methods-
-(Void) egoRefreshTableHeaderDidTriggerRefresh :( EGORefreshTableHeaderView *) view {
If (self. refreshperformancefunc & self. refreshperformancecompleted ){
Self. refreshperformancefunc ();

Double delayInSeconds = 3.0;
Dispatch_time_t popTime = dispatch_time (DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC );
Dispatch_after (popTime, dispatch_get_main_queue (),
Self. refreshperformancecompleted );
}
}
 
-(BOOL) egorefreshtableheaderperformanceisloading :( EGORefreshTableHeaderView *) view {
Return self. isRefreshing;
}
 
-(NSDate *) egorefreshtableheader1_celastupdated :( EGORefreshTableHeaderView *) view {
Return [NSDate date];
}
 
# Pragma mark-UIScrollViewDelegate Methods-
-(Void) scrollViewWillBeginDecelerating :( UIScrollView *) scrollView {
Self. currentOffsetPoint = scrollView. contentOffset;
}
 
-(Void) scrollViewDidScroll :( UIScrollView *) scrollView {
CGPoint pt = scrollView. contentOffset;
If (self. currentOffsetPoint. y <pt. y ){
[Self. loadMoreFooterView loadMoreScrollViewDidScroll: scrollView];
} Else {
[Self. refreshHeaderView egoRefreshScrollViewDidScroll: scrollView];
}
}
 
-(Void) scrollViewDidEndDragging :( UIScrollView *) scrollView willDecelerate :( BOOL) decelerate {
CGPoint pt = scrollView. contentOffset;
If (self. currentOffsetPoint. y <pt. y ){
[Self. loadMoreFooterView loadMoreScrollViewDidEndDragging: scrollView];
} Else {
[Self. refreshHeaderView egoRefreshScrollViewDidEndDragging: scrollView];
}

If (! Decelerate & self. loadImagesForVisiableRowsFunc ){
Self. loadImagesForVisiableRowsFunc ();
}
}
 
-(Void) scrollViewDidEndDecelerating :( UIScrollView *) scrollView {
If (self. loadImagesForVisiableRowsFunc ){
Self. loadImagesForVisiableRowsFunc ();
}
}
 
# Pragma mark-download image async-
-(Void) appImageDidLoad :( NSIndexPath *) indexPath {
If (self. appImageDownloadCompleted ){
Self. appImageDownloadCompleted (indexPath );
}
}


Use of ELTableViewController

Create a new controller inherited from: ELTableViewController;

Override parent class initBlocks method:


[Cpp]
# Pragma mark-private methods-
-(Void) loadDataSource {
Self. dataSource = [NSMutableArray array];
[Self. dataSource addObject: @ "performance_1"];
[Self. dataSource addObject: @ "performance_2"];
[Self. dataSource addObject: @ "dataSource_3"];
[Self. dataSource addObject: @ "dataSource_4"];
[Self. dataSource addObject: @ "performance_5"];
[Self. dataSource addObject: @ "performance_6"];
[Self. dataSource addObject: @ "performance_7"];
[Self. dataSource addObject: @ "performance_8"];
[Self. dataSource addObject: @ "performance_9"];
[Self. dataSource addObject: @ "performance_10"];
}
 
-(Void) initBlocks {
_ Block TestViewController * blockedSelf = self;

// Load more
Self. loadmoreperformancefunc = ^ {
[BlockedSelf. dataSource addObject: @ "loadMoreDataSourceBlock_1"];
[BlockedSelf. dataSource addObject: @ "loadMoreDataSourceBlock_2"];
[BlockedSelf. dataSource addObject: @ "loadMoreDataSourceBlock_3"];
[BlockedSelf. dataSource addObject: @ "loadMoreDataSourceBlock_4"];
[BlockedSelf. dataSource addObject: @ "loadmoreperformanceblock_5"];

BlockedSelf. isLoadingMore = YES;
[Self. tableView reloadData];

NSLog (@ "loadmoreperformanceblock was invoked ");
};

// Load more completed
Self. loadmoreperformancecompleted = ^ {
BlockedSelf. isLoadingMore = NO;
[BlockedSelf. loadMoreFooterView loadmorescrollviewperformancedidfinishedloading: self. tableView];

NSLog (@ "after loadMore completed ");
};

// Refresh
Self. refreshperformancefunc = ^ {
BlockedSelf. dataSource = [NSMutableArray array];
[BlockedSelf. dataSource addObject: @ "refreshDataSourceBlock_1"];
[BlockedSelf. dataSource addObject: @ "refreshDataSourceBlock_2"];
[BlockedSelf. dataSource addObject: @ "refreshDataSourceBlock_3"];
[BlockedSelf. dataSource addObject: @ "refreshDataSourceBlock_4"];
[BlockedSelf. dataSource addObject: @ "refreshDataSourceBlock_5"];

BlockedSelf. isRefreshing = YES;
[Self. tableView reloadData];

NSLog (@ "refreshperformanceblock was invoked ");
};

// Refresh completed
Self. refreshperformancecompleted = ^ {
BlockedSelf. isRefreshing = NO;
[BlockedSelf. loadMoreFooterView loadmorescrollviewperformancedidfinishedloading: self. tableView];

NSLog (@ "after refresh completed ");
};

Self. cellForRowAtIndexPathDelegate = ^ (UITableView * tableView, NSIndexPath * indexPath ){
Static NSString * cellIdentifier = @ "cellIdentifier ";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
If (! Cell ){
Cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: cellIdentifier] autorelease];
}

Cell. textLabel. text = [blockedSelf. dataSource objectAtIndex: indexPath. row];

NSLog (@ "block: cellForRowAtIndexPathBlock has been invoked .");

Return cell;
};

Self. heightForRowAtIndexPathDelegate = ^ (UITableView * tableView, NSIndexPath * indexPath ){
NSLog (@ "block: heightForRowAtIndexPathBlock has been invoked .");
Return 601_f;
};

Self. didSelectRowAtIndexPathDelegate = ^ (UITableView * tableView, NSIndexPath * indexPath ){
NSLog (@ "block: didSelectRowAtIndexPathDelegate has been invoked .");
};

}

 

 


 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.