2012-02-08 9 views
0

私はインターネットからニュースを読み込むためにテーブルビューを持っています。私はviewDidUnloadのすべてのプロパティをゼロにしようとしています。viewDidUnloadのメモリ管理 - 配列とオブジェクトの両方をnilにする必要はありませんか?

- (void)viewDidUnload 
{ 
    self.newsArray = nil; 
    self.newsTableView = nil; 
    self.indicatorView = nil; 
// self.iconDownLoader = nil; 
    self.downloadArray = nil; 

    [super viewDidUnload]; 
} 

viewDidUnloadでアプリがクラッシュするたびに発生します。私がself.iconDownLoader = nilとコメントしても問題ありません。だから、なぜこれが起こるの?ありがとうございます。

--------------------- NewsViewController.m --------------------- -----

// 
// NewsViewController.m 
// 
// Created by on 18/01/12. 
// Copyright (c) 2012 __MyCompanyName__. All rights reserved. 
// 

#import "NewsViewController.h" 
#import "ASIHTTPRequest.h" 
#import "SBJson.h" 
#import "NewsModel.h" 
#import "NewsDetailViewController.h" 

#define kCustomRowCount 6 
#define IconPlaceHolder @"Spinner" 

@implementation NewsViewController 

@synthesize appDelegate, newsTableViewCell, newsTableView, indicatorView; 
@synthesize iconDownLoader, newsArray, downloadArray; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 

     // setup appDelegate 
     self.appDelegate = (SydneyAppDelegate *)[[UIApplication sharedApplication] delegate]; 

     // initial arrays 
     self.newsArray = [[NSMutableArray alloc] init]; 
     self.downloadArray = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
} 

#pragma mark - View lifecycle 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    if(self.appDelegate.reachable) { 
     [self getNews]; 
    } 
    else 
    { 
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Connection" message:@"No Internet connection. Please try again later." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
     [alert show]; 
    } 
} 

- (void)viewDidUnload 
{ 
    self.newsArray = nil; 
    self.newsTableView = nil; 
    self.indicatorView = nil; 
// self.iconDownLoader = nil; 
    self.downloadArray = nil; 

    [super viewDidUnload]; 
} 

#pragma mark - ASIHTTPRequest 

- (void) getNews 
{ 
    NSURL *url = [NSURL URLWithString:@"http://ferrarimaseratisydney.com/api/getPublicNews.html"]; 
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 
    [request setDelegate:self]; 
    [request startAsynchronous]; 
} 

- (void) requestFinished:(ASIHTTPRequest *)request 
{ 
    NSString *responseString = [request responseString]; 
    NSArray *json = [responseString JSONValue]; 

    for (id aNewsInJson in json) 
    { 
     NewsModel *aNews = [[NewsModel alloc] initWithJson:aNewsInJson]; 
     [self.newsArray addObject:aNews]; 
    } 

    [self.indicatorView removeFromSuperview]; 

    [self.newsTableView reloadData]; 
} 

- (void) requestFailed:(ASIHTTPRequest *)request 
{ 
    NSError *error; 
    error = [request error]; 
} 

#pragma mark - Table view delegate 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 

    // Navigation logic may go here. Create and push another view controller. 
    NewsDetailViewController *newsDetailViewController = [[NewsDetailViewController alloc] init]; 

    // transform news array 
    newsDetailViewController.news = [self.newsArray objectAtIndex:indexPath.row]; 

    // Pass the selected object to the new view controller. 
    [self.navigationController pushViewController:newsDetailViewController animated:YES]; 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [self.newsArray count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"NewsCellIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     [[NSBundle mainBundle] loadNibNamed:@"NewsTableViewCell" owner:self options:nil]; 
     cell = self.newsTableViewCell; 
     self.newsTableViewCell = nil; 
    } 

    // read from newsModel 
    NewsModel *news = [self.newsArray objectAtIndex:indexPath.row]; 

    UILabel *label; 
    label = (UILabel *)[cell viewWithTag:10]; 
    label.text = [NSString stringWithString:news.title]; 
    label = nil; 
    label = (UILabel *)[cell viewWithTag:11]; 
    label.text = [NSString stringWithString:news.description]; 
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:12]; 
    imageView.image = news.image; 

    if (news.image == nil) 
    { 
     imageView.image = [UIImage imageNamed:IconPlaceHolder]; 

     self.iconDownLoader = [[IconDownLoader alloc] init]; 
     self.iconDownLoader.url = news.imageUrl; 
     self.iconDownLoader.delegate = self; 
     self.iconDownLoader.indexPath = indexPath; 
     if (self.appDelegate.ip4 == YES) 
     { 
      self.iconDownLoader.width = 300; 
      self.iconDownLoader.height = 150; 
     } 
     else 
     { 
      self.iconDownLoader.width = 150; 
      self.iconDownLoader.height = 75; 
     } 
     [self.downloadArray addObject:self.iconDownLoader]; 
     [self.iconDownLoader start]; 
    } 
    return cell; 
} 

#pragma mark - IconDownLoaderDelegate 

- (void)iconDownLoadFinsh:(NSData *)imageData row:(NSIndexPath *)indexPath { 

    UITableViewCell *cell = [self.newsTableView cellForRowAtIndexPath:indexPath]; 
    UIImageView *imageView = (UIImageView *)[cell viewWithTag:12]; 
    if (imageData != 0) 
    { 
     imageView.image = [UIImage imageWithData:imageData]; 
    } 
    else 
    { 
     imageView.image = [UIImage imageNamed:@"icon57"]; 
    } 
    NewsModel *newsModel = [self.newsArray objectAtIndex:indexPath.row]; 
    newsModel.image = [UIImage imageWithData:imageData]; 
} 

@end 

----------------------- IconDownLoader.m ---------- ---------ここ

// 
// IconDownLoader.m 
// 
// Created by on 24/11/11. 
// Copyright (c) 2011 __MyCompanyName__. All rights reserved. 
// 

#import "IconDownLoader.h" 
#import "ASIHTTPRequest.h" 

@implementation IconDownLoader 

@synthesize delegate = _delegate; 
@synthesize url = _url; 
@synthesize indexPath = _indexPath; 
@synthesize width = _width; 
@synthesize height = _height; 
@synthesize request = _request; 

- (void)start { 

    NSString *originalString = @"width=%s&height=%s"; 
    NSString *newString = [NSString stringWithFormat:@"width=%d&height=%d&type=jpg", self.width, self.height]; 

    NSString *resizedURL = [self.url stringByReplacingOccurrencesOfString:originalString withString:newString]; 

    NSURL *url = [NSURL URLWithString:[resizedURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 
    _request = [ASIHTTPRequest requestWithURL:url]; 
    if (_indexPath) { 
     _request.userInfo = [NSDictionary dictionaryWithObject:_indexPath forKey:@"indexPath"]; 
    } 
    [_request setDelegate:self]; 
    [_request startAsynchronous]; 
} 

- (void)requestFinished:(ASIHTTPRequest *)request { 

    NSInteger statusCode = request.responseStatusCode; 
    switch (statusCode) { 
     case 401: // Not Authorized: either you need to provide authentication credentials, or the credentials provided aren't valid. 
      break; 

     case 200: { 
      NSData *responseData = [request responseData]; 
      if (!responseData) { 
       UIAlertView *alertView; 
       alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"Download failed in row %d", _indexPath.row] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
       return; 
      } 
      [_delegate iconDownLoadFinsh:responseData row:[request.userInfo objectForKey:@"indexPath"]]; 
     } 
      break; 

     default:{ 

     } 
    } 
} 

- (void)dealloc { 
    if (_request != nil) { 
     [_request clearDelegatesAndCancel]; 
    } 
} 

@end 

答えて

1

通常、viewDidUnloadには、自分が所有するnibオブジェクトへの参照をすべて解放してゼロにする必要があります。

つまり、モデルのオブジェクトは、多くのメモリを消費する場合にも、viewDidUnloadに破棄することができます。 viewDidUnloadviewDidLoadに対応しているので、viewDidUnloadのオブジェクトを破棄し、viewDidLoadに作成することをお勧めします。また、ビューコントローラが解放されたときにviewDidUnloadではなくであることを覚えておく必要があります。

あなたの場合、init...で作成しただけなので、私はnewsArraydownloadArrayをリリースしません。代わりに​​を送信するだけです。

クラッシュについては、セルが画像を必要とするたびに新しい共有アイコンダウンローダを作成します。これは少し面倒です。共有ダウンローダインスタンスが必要な場合は、各セルごとに再作成しないでください。あなたが作成したすべてのダウンローダをivar配列に保存したいのは、各ダウンローダがワンショットであり、単一のイメージを読み込む責任があるからです。

+0

ありがとうございます、私はicondownloaderをappdelegateに入れます – ThinkChris

1

ない十分な情報を伝えるために、おそらくあなたは私たちがその時点でnilに参照を設定せずに見ることができないコードのいくつかの他の部分に直接iconDownloaderをリリースしてきました。

次に、viewDidUnloadで無効な参照を解放しようとしています。 @synthesizeについては

、使用:

@synthesize iconDownLoader = _iconDownloader; 

、代わりにiconDownloaderのself.icondownloderを使用するようにコンパイラの警告のすべてを修正し、「解放」のすべての使用を排除し(あなたの財産を保持しているとしてマークされていると仮定するとそのはず)。

実際、あなたのすべての問題は、プロパティが保持プロパティではないため、iconDOwnloaderを作成してすぐに解放されるということです。

+0

ありがとうございます。次のprojでxxx = _xxxを使用します。 – ThinkChris

関連する問題