我需要在每个页面中使用 uipageviewcontroller 呈现webview。每个页面都是一个tableview,webview是tableviewcell的属性。
现在的问题是:
翻页时会有延迟,因为加载网页视图并展示它会非常耗时。所以我想通过preload webview来消除这种延迟。我知道uipageviewcontroller将前一个和下一个tableviewcontroller预加载到当前的一个,但它只将它们的视图加载到内存中。
因此,在调用tableviewdatasource方法之前,不会创建单元格,更不用说它们的属性,在我的情况下是webview。那么如何在不改变给定视图架构的情况下预加载这些webview呢?或者对给定的架构进行一些改动是否有更好的方法?
答案 0 :(得分:0)
在pageviewcontroller委托方法中预加载webview
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerBeforeViewController:(UIViewController *)viewController;
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
viewControllerAfterViewController:(UIViewController *)viewController;
在pageviewcontroller委托方法中,您需要找到方向,如果是下一个,则在下一个viewcontroller旁边加载,然后在preved viewcontroller之前释放。对于例如你有page1,page2,page3,page4,page5,page6,page7。假设您在横向显示两个页面,然后在pageviewcontroller初始化时加载第1页,第2页,第3页和第4页的Web视图。
在委托方法中检查方向如果是,则加载page5和page6的webview。在屏幕上显示您将有page3和page4。当你到第4页和第5页加载下2页并释放第1页和第2页时。
所以,请立即保持上一个和下一个viewcontroller。请发布其他视图控制器,它将帮助您解决问题并调整内存,因此性能也会很好。
答案 1 :(得分:0)
UITableView管理细胞在屏幕上渲染时的细胞生命周期和位置。你想在这里实现的是UITableView无法容纳的东西。
在我看来,只有一件事要做:抛出UITableView并从头开始自己的TableView(见下面的例子):
@protocol TableViewDataSource <NSObject>
- (NSInteger) numberOfRows;
- (UIView *) cellForRow:(NSInteger) row;
- (void) itemAdded;
- (void) itemAddedAtIndex:(NSInteger)index;
@end
@interface TableView : UIView <UIScrollViewDelegate>
@property (nonatomic, assign) id<UIScrollViewDelegate> delegate;
// the object that acts as the data source for this table
@property (nonatomic, assign) id<TableViewDataSource> datasource;
// the UIScrollView that hosts the table contents
@property (nonatomic, assign, readonly) UIScrollView* scrollView;
-(UIView*) dequeueReusableCell;
-(NSArray*) visibleCells;
// forces the table to dispose of all the cells and re-build the table.
-(void) reloadData;
-(void) registerClassForCells: (Class)cellClass;
@end
const float ROW_HEIGHT = 50.0f;
@implementation TableView
{
UIScrollView* _scrollView;
id<TableViewDataSource> _datasource;
// a set of cells which are re-useable
NSMutableSet* _reuseCells;
// the Class which indicates the cell type
Class _cellClass;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectNull];
[self addSubview:_scrollView];
_scrollView.delegate = self;
_scrollView.backgroundColor = [UIColor clearColor];
self.backgroundColor = [UIColor clearColor];
_reuseCells = [[NSMutableSet alloc] init];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
_scrollView.frame = self.frame;
[self refreshView];
}
#pragma mark - cell lifecycle
-(void) refreshView
{
if (CGRectIsNull(_scrollView.frame))
{
return;
}
_scrollView.contentSize = CGSizeMake(_scrollView.bounds.size.width, [_datasource numberOfRows] * ROW_HEIGHT);
for(UIView* cell in [self cellSubviews])
{
if (cell.frame.origin.y + cell.frame.size.height < _scrollView.contentOffset.y)
{
[self recycleCell:cell];
}
if (cell.frame.origin.y > _scrollView.contentOffset.y + _scrollView.frame.size.height)
{
[self recycleCell:cell];
}
}
int firstVisibleIndex = MAX(0, floor(_scrollView.contentOffset.y / ROW_HEIGHT));
int lastVisibleIndex = MIN([_datasource numberOfRows],
firstVisibleIndex + 1 + ceil(_scrollView.frame.size.height / ROW_HEIGHT));
for (int row = firstVisibleIndex; row < lastVisibleIndex; row++)
{
UIView* cell = [self cellForRow:row];
if (!cell)
{
UIView* cell = [_datasource cellForRow:row];
float topEdgeForRow = row * ROW_HEIGHT;
cell.frame = CGRectMake(0, topEdgeForRow, _scrollView.frame.size.width, ROW_HEIGHT);
[_scrollView insertSubview:cell atIndex:0];
}
}
}
-(void) recycleCell:(UIView*)cell
{
[_reuseCells addObject:cell];
[cell removeFromSuperview];
}
-(UIView*) cellForRow:(NSInteger)row
{
float topEdgeForRow = row * SHC_ROW_HEIGHT;
for(UIView* cell in [self cellSubviews])
{
if (cell.frame.origin.y == topEdgeForRow)
{
return cell;
}
}
return nil;
}
-(NSArray*)cellSubviews
{
NSMutableArray* cells = [[NSMutableArray alloc] init];
for(UIView* subView in _scrollView.subviews)
{
if ([subView isKindOfClass:[SHCTableViewCell class]])
{
[cells addObject:subView];
}
}
return cells;
}
#pragma mark - UIScrollViewDelegate handlers
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[self refreshView];
// forward the delegate method
if ([self.delegate respondsToSelector:@selector(scrollViewDidScroll:)]){
[self.delegate scrollViewDidScroll:scrollView];
}
}
#pragma mark - UIScrollViewDelegate forwarding
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ([self.delegate respondsToSelector:aSelector]) {
return YES;
}
return [super respondsToSelector:aSelector];
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
if ([self.delegate respondsToSelector:aSelector]) {
return self.delegate;
}
return [super forwardingTargetForSelector:aSelector];
}
#pragma mark - public API methods
-(void) registerClassForCells: (Class)cellClass
{
_cellClass = cellClass;
}
-(NSArray*) visibleCells
{
NSMutableArray* cells = [[NSMutableArray alloc] init];
for(UIView* subView in [self cellSubviews])
{
[cells addObject:subView];
}
NSArray* sortedCells = [cells sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
UIView* view1 = (UIView*)obj1;
UIView* view2 = (UIView*)obj2;
float result = view2.frame.origin.y - view1.frame.origin.y;
if (result > 0.0) {
return NSOrderedAscending;
} else if (result < 0.0){
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
return sortedCells;
}
-(UIView*)dequeueReusableCell
{
// first obtain a cell from the re-use pool
UIView* cell = [_reuseCells anyObject];
if (cell) {
[_reuseCells removeObject:cell];
}
if (!cell) {
cell = [[_cellClass alloc] init];
}
return cell;
}
-(void)reloadData
{
// remove all subviews
[[self cellSubviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self refreshView];
}
#pragma mark - property getters / setters
- (UIScrollView *)scrollView
{
return _scrollView;
}
-(id<TableViewDataSource>)datasource
{
return _datasource;
}
-(void)setDatasource:(id<TableViewDataSource>)datasource
{
_datasource = datasource;
[self refreshView];
}
@end