4 Stimmen

Popping UIView stürzt App ab

Ich bin im Grunde schieben eine UIView von einem UITableViewController und alles, was es enthält, ist ein UIWebView. Allerdings, wenn ich die UIView entfernen, um zurück zu den UITableView die app stürzt ab.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
if (indexPath.row == websiteCell) {
    NSString *urlPath = [NSString stringWithFormat:@"http://%@", exhibitor.website];
    WebViewController *webViewController = [[WebViewController alloc] initWithURLString:urlPath];

    // Pass the selected object to the new view controller.
    [self.parentViewController presentModalViewController:webViewController animated:YES];
    [webViewController release];
}

}

Wenn ich das [webViewController release] auskommentiere, stürzt die App nicht ab, aber ich weiß, dass dies ein Leck wäre.

Nachfolgend finden Sie den Code für den Webbrowser:

#import "WebViewController.h"

@implementation WebViewController

@synthesize webBrowserView;
@synthesize urlValue;
@synthesize toolBar;
@synthesize spinner;
@synthesize loadUrl;

-(id)initWithURLString:(NSString *)urlString {
if (self = [super init]) {
    urlValue = urlString;
}

return self;
}

#pragma mark WebView Controls
- (void)goBack {
[webBrowserView goBack];
}

- (void)goForward {
[webBrowserView goForward];
}

- (void)reload {
[webBrowserView reload];
}

- (void)closeBrowser {
[self.parentViewController dismissModalViewControllerAnimated:YES];
}

#pragma end

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];

CGRect contentRect = self.view.bounds;
//NSLog(@"%f", contentRect.size.height);
float webViewHeight = contentRect.size.height - 44.0f;  // navBar = 44
float toolBarHeight = contentRect.size.height - webViewHeight;

// navigation bar
UINavigationBar *navBar = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 20, contentRect.size.width, 44)] autorelease];
navBar.delegate = self;

UIBarButtonItem *doneButton = [[[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:nil action:@selector(closeBrowser)] autorelease];
UINavigationItem *item = [[[UINavigationItem alloc] initWithTitle:@"CEDIA10"] autorelease];
item.leftBarButtonItem = doneButton;

[navBar pushNavigationItem:item animated:NO];
[self.view addSubview:navBar];

// web browser
webBrowserView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 64, contentRect.size.width, webViewHeight)];
webBrowserView.delegate = self;
webBrowserView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
webBrowserView.scalesPageToFit = YES;
[self.view addSubview:webBrowserView];

// buttons
UIBarButtonItem *backButton = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"arrowleft.png"] style:UIBarButtonItemStylePlain target:self action:@selector(goBack)] autorelease];
UIBarButtonItem *fwdButton = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"arrowright.png"] style:UIBarButtonItemStylePlain target:self action:@selector(goForward)] autorelease];
UIBarButtonItem *refreshButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(reload)] autorelease];
UIBarButtonItem *flexSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease];
UIBarButtonItem *fixSpace = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil] autorelease];
[fixSpace setWidth: 40.0f];

spinner = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite] autorelease];
[spinner startAnimating];
UIBarButtonItem *loadingIcon = [[[UIBarButtonItem alloc] initWithCustomView:spinner] autorelease];

NSArray *toolBarButtons = [[NSArray alloc] initWithObjects: fixSpace, backButton, fixSpace, fwdButton, flexSpace, loadingIcon, flexSpace, refreshButton, nil];

// toolbar
toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, webViewHeight, contentRect.size.width, toolBarHeight)];
toolBar.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
toolBar.items = toolBarButtons;

[self.view addSubview:toolBar];

// load the request
NSURL *requestString = [NSURL URLWithString:urlValue];
[webBrowserView loadRequest:[NSURLRequest requestWithURL: requestString]];

[toolBarButtons release];
}

- (void)viewWillDisappear
{
if ([webBrowserView isLoading]) {
    [webBrowserView stopLoading];
    webBrowserView.delegate = nil;
}
}

#pragma mark UIWebView

- (void)webViewDidStartLoad:(UIWebView*)webView {
[spinner startAnimating];
}

- (void)webViewDidFinishLoad:(UIWebView*)webView {
[spinner stopAnimating];
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
loadUrl = [[request URL] retain];

if ([[loadUrl scheme] isEqualToString: @"mailto"]) {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"CEDIA10" message:@"Do you want to open Mail and exit AREC10?" delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
    [alert show]; 
    [alert release];

    return NO;
}

[loadUrl release];

return YES;
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
[spinner stopAnimating];
if (error.code == -1009) {
    // no internet connection
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"CEDIA10" message:@"You need an active Internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
    [alert show]; 
    [alert release];
}
}

#pragma mark UIAlertView

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
    [[UIApplication sharedApplication] openURL:loadUrl];
    [loadUrl release];
}
}

- (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.
[webBrowserView release];
[urlValue release];
[toolBar release];
[spinner release];
[loadUrl release];

webBrowserView = nil;
webBrowserView.delegate = nil;
urlValue = nil;
toolBar = nil;
spinner = nil;
loadUrl = nil;
}

- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;

}

- (void)dealloc {
[webBrowserView release];
[urlValue release];
[toolBar release];
[spinner release];
[loadUrl release];

webBrowserView.delegate = nil;
urlValue = nil;
toolBar = nil;
spinner = nil;
loadUrl = nil;

[super dealloc];
}

@end

Nachfolgend finden Sie das Absturzprotokoll, das ich erhalte:

Date/Time:       2010-05-13 11:58:20.023 +1000
OS Version:      iPhone OS 3.1.3 (7E18)
Report Version:  104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread:  0

Thread 0 Crashed:
0   libSystem.B.dylib               0x00090b2c __kill + 8
1   libSystem.B.dylib               0x00090b1a kill + 4
2   libSystem.B.dylib               0x00090b0e raise + 10
3   libSystem.B.dylib               0x000a7e34 abort + 36
4   libstdc++.6.dylib               0x00066390 __gnu_cxx::__verbose_terminate_handler() + 588
5   libobjc.A.dylib                 0x00008898 _objc_terminate + 160
6   libstdc++.6.dylib               0x00063a84 __cxxabiv1::__terminate(void (*)()) + 76
7   libstdc++.6.dylib               0x00063afc std::terminate() + 16
8   libstdc++.6.dylib               0x00063c24 __cxa_throw + 100
9   libobjc.A.dylib                 0x00006e54 objc_exception_throw + 104
10  CoreFoundation                  0x00095bf6 -[NSObject doesNotRecognizeSelector:] + 106
11  CoreFoundation                  0x0001ab12 ___forwarding___ + 474
12  CoreFoundation                  0x00011838 _CF_forwarding_prep_0 + 40
13  QuartzCore                      0x0000f448 CALayerCopyRenderLayer + 24
14  QuartzCore                      0x0000f048 CA::Context::commit_layer(_CALayer*, unsigned int, unsigned int, void*) + 100
15  QuartzCore                      0x0000ef34 CALayerCommitIfNeeded + 336
16  QuartzCore                      0x0000eedc CALayerCommitIfNeeded + 248
17  QuartzCore                      0x00011ee8 CA::Context::commit_root(void*, void*) + 52
18  QuartzCore                      0x00011e80 x_hash_table_foreach + 64
19  QuartzCore                      0x00011e2c CA::Transaction::foreach_root(void (*)(void*, void*), void*) + 40
20  QuartzCore                      0x0000bb68 CA::Context::commit_transaction(CA::Transaction*) + 1068
21  QuartzCore                      0x0000b46c CA::Transaction::commit() + 276
22  QuartzCore                      0x000135d4 CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 84
23  CoreFoundation                  0x0000f82a __CFRunLoopDoObservers + 466
24  CoreFoundation                  0x00057340 CFRunLoopRunSpecific + 1812
25  CoreFoundation                  0x00056c18 CFRunLoopRunInMode + 44
26  GraphicsServices                0x000041c0 GSEventRunModal + 188
27  UIKit                           0x00003c28 -[UIApplication _run] + 552
28  UIKit                           0x00002228 UIApplicationMain + 960
29  CEDIA10                         0x00002e16 main (main.m:14)
30  CEDIA10                         0x00002db8 start + 32

Irgendwelche Ideen, warum die App abstürzt?

2voto

Adun Punkte 71

Ich habe gerade herausgefunden, was es war. In der WebViewController's dealloc hatte ich dies:

- (void)dealloc {
[webBrowserView release];
[urlValue release];
[toolBar release];
[spinner release];
[loadUrl release];

webBrowserView.delegate = nil;
urlValue = nil;
toolBar = nil;
spinner = nil;
loadUrl = nil;

[super dealloc];

}

Durch die Umstellung auf dieses System funktioniert es einwandfrei und es treten keine Lecks auf:

- (void)dealloc {
webBrowserView.delegate = nil;
[webBrowserView stopLoading];
urlValue = nil;
toolBar = nil;
spinner = nil;
loadUrl = nil;

[webBrowserView release];
[urlValue release];
[toolBar release];
[spinner release];
[loadUrl release];

[super dealloc];
}

Also habe ich nicht den Delegaten vor der Freigabe nullen, so dass ich Webview muss noch senden Anrufe an einen Delegaten, die nicht existiert.

1voto

Ben Scheirman Punkte 39742

Ich würde wetten, dass es die webView ist, die noch Ereignisse an seinen Delegaten (Ihre jetzt dealloc'ed View Controller) sendet.

Haben Sie auch die Xcode Build & Analyze ausführen, um potenzielle Speicherlecks / über Releases zu finden?

1voto

rdnie Punkte 101

Das Problem ist, dass Sie eigentlich die webBrowserView delegate a nil NACHDEM Sie es veröffentlicht haben. Wenn Sie alles auf Null setzen, BEVOR Sie es freigeben, erzeugen Sie Speicherlecks (Senden von [nil release] tut nichts).

Stattdessen sollte es lauten

- (void)dealloc {
    [webBrowserView stopLoading];
    webBrowserView.delegate = nil;

    [webBrowserView release];
    [urlValue release];
    [toolBar release];
    [spinner release];
    [loadUrl release];

    [super dealloc];
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X