Objective-C на iPhone - сбой панели вкладок - PullRequest
0 голосов
/ 04 марта 2011

Я относительно плохо знаком с Objective-C и кодированием.Я попытался сделать небольшую разработку самостоятельно, но теперь застрял на том, что, вероятно, является ошибкой новичка.Я создал контроллер панели вкладок с 5 представлениями, одним из которых является UIWebView.У меня работает Webview, и он загружается, но когда я выбираю другую вкладку, приложение вылетает.Пожалуйста, найдите мой код ниже, и любая помощь будет оценена!

#import <UIKit/UIKit.h>


@interface LiveViewController : UIViewController {

IBOutlet UIWebView *liveView;

}

@property (nonatomic, retain) UIWebView *liveView;

@end



    #import "LiveViewController.h"

@implementation LiveViewController

@synthesize liveView; 



// The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization.
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [self.liveView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.britishseapower.co.uk/live/"]]];
[super viewDidLoad];
}

- (void)webViewDidStartLoad:(UIWebView *)liveView
{
    // starting the load, show the activity indicator in the status bar
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

- (void)webViewDidFinishLoad:(UIWebView *)liveView
{
    // finished loading, hide the activity indicator in the status bar
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}

- (void)liveView:(UIWebView *)liveView didFailLoadWithError:(NSError *)error
{
    // load error, hide the activity indicator in the status bar
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    // report the error inside the webview
    NSString* errorString = [NSString stringWithFormat:
                             @"<html><center><font size=+5 color='red'>An error occurred:<br>%@</font></center></html>",
                             error.localizedDescription];
    [self.liveView loadHTMLString:errorString baseURL:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    if ( [self.liveView loading] ) {
        [self.liveView stopLoading];
    }
    self.liveView.delegate = nil;    // disconnect the delegate as the webview is hidden
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}


- (void)dealloc {
    [liveView release];
    [UIWebView release];
    [LiveViewController release];
    [super dealloc];
}


@end

Большое спасибо,

Райан

Ответы [ 4 ]

2 голосов
/ 04 марта 2011
[UIWebView release]; [LiveViewController release];

Это то, что делает ваше приложение аварийным. Неправильно отправлять сообщение о выпуске самому классу. То, что вы сделали с [liveView release]; достаточно (с вызовом [super dealloc];.)

Вы также должны установить для делегата значение nil в методе dealloc, как в методе viewWillDisappear self.liveView.delegate = nil;. Таким образом, вы обязательно избежите дальнейших сообщений, отправляемых в LiveViewController из UIWebView.

Вы должны прочитать немного больше документации по Objective-C, чтобы лучше понять, как она работает.

1 голос
/ 04 марта 2011

Одна из наиболее распространенных причин, по которой может произойти сбой приложения, - это ссылка или отправка сообщения объекту, который уже был освобожден из памяти.И этот тип ошибки может быть легко найден с помощью NSZombieEnabled и заглядывая в консольное сообщение.Так что, если вы еще не пробовали это, это первое, что вы должны сделать.

Проблема может быть в LiveViewController, но может быть и в других контроллерах представления.Я бы не поверил, что проблема в LiveViewController на 100%, потому что контроллер представления не будет пытаться освободить свое представление, когда представление не отображается, пока не получит предупреждение памяти.И вы запускаете приложение с помощью симулятора, вряд ли у него будет предупреждение о памяти, если вы его не симулируете.

Вы, вероятно, знаете, что контроллер представления никогда не создает представление, если представление не используется объектом.У одного из других контроллеров представления может быть глупая ошибка в процессе загрузки представления, которая вызывает сбой.Или, возможно, вы выпустили другой контроллер вида по ошибке.Убедитесь на 100%, что другие контроллеры представлений не имеют проблем с отображением их представлений самостоятельно, когда вы продолжаете переключаться между их представлениями (не показывая LiveViewController).

Итак, я бы попробовал NSZombieEnabled и проверить,он получает доступ к освобожденному объекту, и если он делает, что это за объект.Также я дважды проверю, связана ли проблема с LiveViewController.Если это не поможет, я буду записывать сообщение, когда LiveViewController и его liveView будут освобождены (для liveView вам нужно создать его подкласс).Поскольку свойство delegate почти всегда не сохраняет объект, если объект LiveViewController освобожден (что не должно происходить), а liveView по-прежнему имеет ссылку на него в свойстве делегата, это приведет к сбою.

1 голос
/ 04 марта 2011

Не уверен, если это связано, но я заметил, что вы не устанавливаете себя в качестве делегата где-либо в коде, что означает, что он должен быть подключен в Интерфейсном Разработчике.Теперь, когда представление исчезает, вы разрываете это соединение, но если представление появилось вновь и не было ранее выгружено, это соединение останется разорванным.

0 голосов
/ 04 марта 2011

Подобные сбои почти всегда связаны с освобождением объекта, который уже был освобожден и освобожден.
Позвольте XCode помочь вам найти ошибку. В XCode 4:
- На панели инструментов выберите список схем и выберите «Редактировать схему»
- Выберите «Run Your.app» в списке слева. - В разделе «Переменные среды» добавьте следующие пары имя / значение в соответствующие столбцы:
CFZombieLevel 3
NSZombieEnabled ДА

Теперь при отладке вашего приложения вы получите сообщение о том, что -release вызывается для объекта, у которого уже -retainCount равен нулю. Теперь у вас есть хорошая подсказка, чтобы начать расследование.

Обратите внимание, что эти флаги предотвращают освобождение объектов, поэтому лучше включать их по мере необходимости, чтобы избежать ошибок нехватки памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...