简体   繁体   中英

UIWebView controller troubles

guys. I have two view controllers with two uiwebviews. Here is my code: First controller:

#import "articleView.h"

@interface articleView (Private)
- (BOOL) string:(NSString *)string containsString:(NSString *) stringToFind;
@end
@implementation articleView
@synthesize item;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    center = loaderView.bounds;
    loadingArticleContent = 0;
    if ([item objectForKey:@"article"] == nil) {
        [LoadingView showLoadingViewAddedTo:loaderView];
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:1.0];
        loaderView.alpha = 0.7;
        [UIView commitAnimations];
        NSString *link = [item objectForKey:@"link"];
        currentArticleLoader *loader = [[currentArticleLoader alloc] init];
        loader.link = link;
        loader.delegate = self;
        [loader load];
    } else {
        if (webView.loading == NO) {
            [self loadWebView:(NSString *)[item objectForKey:@"article"]];
        }
    }
    UIBarButtonItem *itemBar = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(showToolbar)];
    self.navigationItem.rightBarButtonItem = itemBar;
    [itemBar release];
    self.title = (NSString *)[item objectForKey:@"title"];
    self.navigationController.toolbar.tintColor = self.navigationController.navigationBar.tintColor;
}
- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    favorited = [[[NSUserDefaults standardUserDefaults] objectForKey:@"favorites"] mutableCopy];
    if (favorited.count == 0) {
        favorited = [[NSMutableArray alloc] init];
        [[NSUserDefaults standardUserDefaults] setObject:favorited forKey:@"favorites"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }
    bought = [[NSUserDefaults standardUserDefaults] boolForKey:@"com.unnamed.habr.full"];
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(share)];
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"28-star.png"] style:UIBarButtonItemStylePlain target:self action:@selector(addToFavorites)];
    UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"71-compass.png"] style:UIBarButtonItemStylePlain target:self action:@selector(openInSafari)];
    if (bought == NO) {
        item2.enabled = NO;
    }
    if ([favorited containsObject:item] == NO) {
        [self setToolbarItems:[NSArray arrayWithObjects:item1, space, item3, space, item2, nil]];
    } else {
        [self setToolbarItems:[NSArray arrayWithObjects:item1, space, item3, nil]];
    }
    [space release];
    [item1 release]; 
    [item2 release];
    [item3 release];
}

- (void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ([self.navigationController isToolbarHidden] == NO) {
        [self.navigationController setToolbarHidden:YES animated:YES];
    }
}
- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
- (void) updated:(NSString *)string {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loaderView.bounds = CGRectMake(-90, 110, 110, 110);
    loaderView.alpha = 0.5;
    [UIView commitAnimations];

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithDictionary:item];
    [dict setValue:string forKey:@"article"];
    item = [[NSDictionary alloc] initWithDictionary:dict];
    [self loadWebView:string];
    [dict release];
}
- (void) loadWebView:(NSString *)body {
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    NSString *title = [item objectForKey:@"title"];
    NSString *blog = [item objectForKey:@"blog"];
    NSString *bloglink = [item objectForKey:@"bloglink"];
    NSString *author = [item objectForKey:@"author"];

    NSString *html = [[NSString alloc] initWithFormat:@"<html><head></script><link rel=\"stylesheet\" href=\"mobile.css\" type=\"text/css\" media=\"all\" charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"></head><body><h3><a href=\"%@\">%@</a> → %@ </h3> </br> %@ </br> <div class=​\"m\">​Автор: %@</div></body></html>", bloglink, blog, title, body, author];
    loadingArticleContent = 1;
    [webView loadHTMLString:html baseURL:baseURL];
    [html release];
}

- (void)addToFavorites {
    [favorited addObject:item];
    [[NSUserDefaults standardUserDefaults] setObject:favorited forKey:@"favorites"];
    [[NSUserDefaults standardUserDefaults] synchronize];
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"124-bullhorn.png"] style:UIBarButtonItemStylePlain target:self action:@selector(share)];
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"71-compass.png"] style:UIBarButtonItemStylePlain target:self action:@selector(openInSafari)];
    [self setToolbarItems:[NSArray arrayWithObjects:item1, space, item2, nil]];
    [space release];
    [item1 release]; 
    [item2 release];
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    if (navigationType == UIWebViewNavigationTypeLinkClicked) {
        NSLog(@"Link: %@", [[request mainDocumentURL] absoluteString]);
        if (bought == YES && loadingArticleContent == 0) {
            if ([self string:[[request mainDocumentURL] absoluteString]  containsString:@"m.habrahabr.ru/blog/"] ||[self string:[[request URL] absoluteString]  containsString:@"m.habrahabr.ru/company/"]) {
                ViewController *controller = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
                controller.url = [request mainDocumentURL];
                controller.title = [NSString stringWithFormat:@"%@", (NSString *)[item objectForKey:@"blog"]];
                [self.navigationController pushViewController:controller animated:YES];
                [controller release];
            } else {
                webViewController *controller = [[webViewController alloc] initWithNibName:@"webViewController" bundle:nil];
                controller.url = [request URL];
                [self.navigationController pushViewController:controller animated:YES];
                [controller release];
            }
        } else {
            UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"iHabr" message:@"Просмотр ссылок возможен только в полной версии программы, как и многие другие функции. Произвести покупку можно на вкладке \"Избранное\"" delegate:self cancelButtonTitle:@"Понятно :(" otherButtonTitles:nil] autorelease];
            [alert show];
        }
        return NO;
    } else if (loadingArticleContent == 1) {
        loadingArticleContent = 0;
        return YES;
    }
    return YES;
}

- (BOOL) string:(NSString *)string containsString:(NSString *) stringToFind {
    NSRange rng = [string rangeOfString:stringToFind];
    return rng.location != NSNotFound;
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"124-bullhorn.png"] style:UIBarButtonItemStylePlain target:self action:@selector(share)];
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"28-star.png"] style:UIBarButtonItemStylePlain target:self action:@selector(addToFavorites)];
    UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"71-compass.png"] style:UIBarButtonItemStylePlain target:self action:@selector(openInSafari)];
    if (bought == NO) {
        item2.enabled = NO;
    }
    if ([favorited containsObject:item] == NO) {
        [self setToolbarItems:[NSArray arrayWithObjects:item1, space, item3, space, item2, nil]];
    } else {
        [self setToolbarItems:[NSArray arrayWithObjects:item1, space, item3, nil]];
    }
    [space release];
    [item1 release]; 
    [item2 release];
    [item3 release];
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1];
    loaderView.alpha = 0;
    [UIView commitAnimations];
}
- (void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"iHabr" message:[NSString stringWithFormat:@"Не удалось загрузить статью. %@", error] delegate:nil cancelButtonTitle:@"Понятно :(" otherButtonTitles: nil] autorelease];
    [alert show];
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loaderView.hidden = YES;
    [UIView commitAnimations];
}

@end

Second controller:

#import "webViewController.h"

@implementation webViewController
@synthesize url;

- (void)viewDidLoad
{
    [super viewDidLoad];
    [myWebView loadRequest:[NSURLRequest requestWithURL:url]];
    UIBarButtonItem *itemBar;
    itemBar = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(showToolbar)];
    self.navigationItem.rightBarButtonItem = itemBar;
    [itemBar release];
    UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
    [self setToolbarItems:[NSArray arrayWithObjects:space, item1, space, item2,item3, space, item4, space, nil]];
    [space release];
    [LoadingView showLoadingViewAddedTo:loadingView];
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loadingView.alpha = 0.7;
    [UIView commitAnimations];
}
- (void) webViewDidStartLoad:(UIWebView *)webView {
    item1.enabled = NO;
    item2.enabled = NO;
    item3.enabled = NO;
    item4.enabled = NO;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loadingView.alpha = 0.7;
    [UIView commitAnimations];
}
- (void) webViewDidFinishLoad:(UIWebView *)webView {
    if (webView.canGoBack) {
        item1.enabled = YES;
    }
    if (webView.canGoForward) {
        item4.enabled = YES;
    }
    item2.enabled = YES;
    item3.enabled = YES;
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loadingView.alpha = 0;
    [UIView commitAnimations];
}
- (void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"iHabr" message:[NSString stringWithFormat:@"Не удалось загрузить страницу. %@", [error userInfo]] delegate:nil cancelButtonTitle:@"Понятно :(" otherButtonTitles: nil] autorelease];
    [alert show];
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    loadingView.alpha = 0;
    [UIView commitAnimations];
}


- (void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ([self.navigationController isToolbarHidden] == NO) {
        [self.navigationController setToolbarHidden:YES animated:YES];
    }
}

After opening URL in second controller, and going back to first, some scrolling up and down - my app showing error EXC_BAD_ACCESS. I turned on NSZombieEnable and now I see this: * -[webViewController respondsToSelector:]: message sent to deallocated instance 0xec624b0 in my console.

You have to be sure to set the delegate property of the web view to nil before it goes away. Do this both in your dealloc and viewDidUnload methods, since viewDidUnload is not always called before dealloc . What's happening is that after your view controller is deallocated, the web view still has a reference to its address, and is trying to send it a message ( -respondsToSelector: ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM