2011-10-10 66 views
1

我相信在學習過程中,下面的代碼段對我來說不是很清楚。我知道一個alloc語句會增加保留數量,但是iOS開發的某些方面仍然讓我感到困惑。有人可以向我解釋爲什麼我需要在以下代碼段中保留聲明嗎?

爲什麼在以下代碼段中需要:[jokesArray retain];

我有一個jokesArray = [[NSArray alloc]init];從我已經閱讀的是足以保留?

有人可以用簡單易懂的方式解釋爲什麼需要保留聲明嗎? (否則應用程序崩潰與一個EXC_BAD_ACCESS。

我有一些善良的人們試圖解釋,但沒有奏效。任何幫助,將不勝感激。

#import "JokesViewController.h" 


@implementation JokesViewController 

- (id)initWithStyle:(UITableViewStyle)style 
{ 
    self = [super initWithStyle:style]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

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

- (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]; 

    jokesArray = [[NSArray alloc]init]; 

    [self getJokes]; 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    [jokesArray release]; 

} 


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

#pragma mark - Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    // Return the number of sections. 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 

    // Return the number of rows in the section. 
    return [jokesArray count]; 
} 

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 





[[cell textLabel]setText:[[jokesArray objectAtIndex:0]objectForKey:@"text"]];  

// [[cell textLabel]setText:@"ok"]; 

    return cell; 
} 

#pragma mark - Table view delegate 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // Navigation logic may go here. Create and push another view controller. 
} 


#pragma mark - Custom Functions 

-(void) getJokes 
{ 
    NSURL *url = [NSURL URLWithString:@"someurl"]; 
    __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 
    [request setCompletionBlock:^{ 
     // Use when fetching text data 
     NSString *responseString = [request responseString]; 

     NSDictionary *resultsDictionary = [responseString objectFromJSONString]; 
     jokesArray = [resultsDictionary allValues]; 

     [jokesArray retain]; //WHY DO I NEED THIS? 


     [self.tableView reloadData]; 

     NSLog(@"%@", [jokesArray description]); 

     // Use when fetching binary data 
    //  NSData *responseData = [request responseData]; 
    }]; 
    [request setFailedBlock:^{ 
     NSError *error = [request error]; 

    }]; 
    [request startAsynchronous]; 
} 

@end 
+0

你是怎麼聲明笑話數組的? – user523234

回答

1

您正在泄漏,因爲在這部分代碼你以前的NSArray分配:

NSDictionary *resultsDictionary = [responseString objectFromJSONString]; 
    jokesArray = [resultsDictionary allValues]; 

    [jokesArray retain]; 

你正在創建一個NSDictionary和更換任何jokesArray指着指向從NSDictionary中,你剛剛創建的數據。 此外,NSDictionary返回的數據是使用便利的初始化方法創建的,這意味着它將在一段時間後發佈,因此您需要保留的原因。

由於您直接修改jokesArray變量,所以在您將其替換爲新對象時,先前分配的NSArray不會被釋放。

+0

不完全。 NSDictionary的allValues返回一個NSArray *。 jokesArry被設置爲allValues正在創建的NSArray(正如你所說,它會在沒有保留的情況下自動發佈)。 –

+0

@GrahamPerks我認爲你是誤解了一些東西。他沒有訪問財產。他直接將它分配給變量,所以jokesArray指向的任何東西都將丟失,從而留下先前分配給泄漏的NSArray。但編輯措辭使其更清晰。 – raixer

+0

當然,你是對的;我只是說它是一個NSArray而不是NSDictionary。 –

1

據我所知,jokesArray並得到保留在初始化

不過,既然你有這樣一行:

jokesArray = [resultsDictionary allValues]; 

您分配一個完整的不同對象的變量,因此你保留一個整體differen t對象。我想你會想要更類似的東西:

[jokesArray addObjectsFromArray:[resultsDictionary allValues]]; 

如果它是一個可變數組。如果沒有,你將不得不進行新的創新。在這種情況下,我可能只會在需要時初始化jokesArray。

1

你有這樣的:

jokesArray = [[NSArray alloc]init]; 

另外,你有這樣的:

jokesArray = [resultsDictionary allValues]; 

第二個呼叫,呼叫allValues,被分配一個全新的jokesArray。你已經分配的那個現在丟失了(假設jokesArray不是保留的屬性),你應該在通過allValues行重新分配之前釋放它。

在allValues調用後需要'保留'的原因是allValues中分配的內存將被標記爲autorelease。如果你想讓這個記憶堅持下去(而且看起來如此),你需要保留它。然後,您在viewDidUnload中釋放的調用將釋放一些內容,並且您對jokesArray的其他引用(例如計數調用)有一些內存可供採取行動。

切換到使用保留屬性將使您免於所有這些麻煩。

相關問題