Search code examples
iosobjective-cuiwebviewuinavigationcontrollernsurlcache

ios custom delegate is null after second click in navigation controller


I have a custom UIWebView (EpubWebView), with a custom NSURLCache (EpubCache) for handling requests. i created a custom delegate for handling request.

EpubCache.h

@protocol EpubCacheDelegate <NSObject>
@required
- (NSCachedURLResponse *)hadleRequest:(NSURLRequest *)request; 
@end

@interface EpubCache : NSURLCache 
@property (nonatomic, weak) id <EpubCacheDelegate> cacheDelegate; 
@end

EpubCache.m

import "EpubCache.h"
@interface EpubCache ()
@end

@implementation EpubCache
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request
{
    return [self.cacheDelegate hadleRequest:request];
}
@end

EpubWebView .h

@interface EpubWebView : UIWebView <UIWebViewDelegate, EpubCacheDelegate>
@property (strong, nonatomic) EpubCache *mLocalCache;
@end

EpubWebView.m

- (void) localInit
{    
    self.mLocalCache = [[EpubCache alloc] init];
    self.mLocalCache.cacheDelegate = self;
    [NSURLCache setSharedURLCache:self.mLocalCache];
}

- (NSCachedURLResponse *)hadleRequest:(NSURLRequest *)request
{
    // return handled request
}

on the other hand i have a navigationcontroller with a tableview and the destination view controller have this webview.

when i ran the app and click on an item in tableview, everything is fine and delegate works as expected.

if i click back and click on other item in tableview, things goes wrong, the cachedResponseForRequest getting called but the hadleRequest wont, i checked and findout that the delegate is null!

i can not figure out what is happening here.

any help would be appreciated.

UPDATE 1

EpubWebView.m

- (id)init
{
    self = [super init];
    if (self)
    {
        [self localInit];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        [self localInit];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if(self)
    {
        [self localInit];
    }
    return self;
}

UPDATE 2

the segue of the tableview that bring up the view controller that contain EpubWebView

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    NSIndexPath *indexPath = [self.collectionView indexPathForCell:sender];
    BookViewController *bookController = segue.destinationViewController;

    bookController.mBook = booksList[indexPath.row];
}

and BookViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    mWebView = [[EpubWebView alloc] initWithFrame:self.mainView.frame];
    [self.mainView addSubView:mWebView];
    [mWebView setBook:self.mBook];

}

Solution

  • You need to make a few modifications. First, remove your "localInit" method, then create a new function in EPubWebView:

    - (void) setCache: (EpubCache *)localCache 
    {
        localCache.cacheDelegate = self;
    }
    

    Now, you can create and hold onto your cache in your BookViewController via these lines in the .m file:

    @interface BookViewController ()
    
    @property (strong, nonatomic) EpubCache *mLocalCache;
    
    @end
    

    and change your BookViewController's viewDidLoad method to look like:

    - (void) viewDidLoad {
    
        self.mLocalCache = [[EpubCache alloc] init];
    
        // only need to do this once, at viewDidLoad time
        [NSURLCache setSharedURLCache:self.mLocalCache ];
    
        [super viewDidLoad];
    
        mWebView = [[EpubWebView alloc] initWithFrame:self.mainView.frame];
        [mWebView setCache:self.mLocalCache];
        [self.mainView addSubView:mWebView];
        [mWebView setBook:self.mBook];
    }