如何使用uipageviewcontroller预加载webview

时间:2018-01-10 06:51:30

标签: ios

我需要在每个页面中使用 uipageviewcontroller 呈现webview。每个页面都是一个tableview,webview是tableviewcell的属性。

现在的问题是:

翻页时会有延迟,因为加载网页视图并展示它会非常耗时。所以我想通过preload webview来消除这种延迟。我知道uipageviewcontroller将前一个和下一个tableviewcontroller预加载到当前的一个,但它只将它们的视图加载到内存中。

因此,在调用tableviewdatasource方法之前,不会创建单元格,更不用说它们的属性,在我的情况下是webview。那么如何在不改变给定视图架构的情况下预加载这些webview呢?或者对给定的架构进行一些改动是否有更好的方法?

2 个答案:

答案 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