Objective c 有人能给我解释一下为什么我;“需要”;以下代码段中的retain语句?
我相信在整个过程中学习,下面的代码段对我来说不是很清楚。我知道alloc语句会增加retain计数,但是iOS开发的某些方面仍然让我感到非常困惑 为什么我需要一个:Objective c 有人能给我解释一下为什么我;“需要”;以下代码段中的retain语句?,objective-c,ios,cocoa-touch,Objective C,Ios,Cocoa Touch,我相信在整个过程中学习,下面的代码段对我来说不是很清楚。我知道alloc语句会增加retain计数,但是iOS开发的某些方面仍然让我感到非常困惑 为什么我需要一个:[jokesArray retain]在下面的代码段中 我有一个jokesArray=[[NSArray alloc]init]从我所读的内容中是否足以保留 有人能用一种简单易懂的方式解释为什么需要retain语句吗?(否则应用程序会因EXC_坏访问而崩溃 我有一些好心的人试图解释,但没有起作用。任何帮助都将不胜感激 #import
[jokesArray retain]代码>在下面的代码段中
我有一个jokesArray=[[NSArray alloc]init]代码>从我所读的内容中是否足以保留
有人能用一种简单易懂的方式解释为什么需要retain语句吗?(否则应用程序会因EXC_坏访问而崩溃
我有一些好心的人试图解释,但没有起作用。任何帮助都将不胜感激
#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
据我所知,jokesArray确实会保留在init上
但是,由于您有这一行:
jokesArray = [resultsDictionary allValues];
您为变量指定了一个完全不同的对象,因此您保留了一个完全不同的对象。我假设您想要的对象更像:
[jokesArray addObjectsFromArray:[resultsDictionary allValues]];
如果是可变数组。如果不是,则必须初始化一个新数组。在这种情况下,我可能只会在需要时初始化JokeArray。您有:
jokesArray = [[NSArray alloc]init];
jokesArray = [resultsDictionary allValues];
另外,您有:
jokesArray = [[NSArray alloc]init];
jokesArray = [resultsDictionary allValues];
第二个调用调用allValues,正在分配一个全新的jokesArray。您已经分配的jokesArray现在已丢失(假设jokesArray不是保留属性),您应该在通过allValues行重新分配之前释放它
在allValues调用后需要“retain”的原因是,在allValues中分配的内存将被标记为自动释放。如果您希望该内存保持不变(看起来确实如此),则需要保留该内存。然后,在viewDidUnload中对release的调用需要释放某些内容,以及对JoksArray的其他引用(例如,计数调用)有一些内存可操作
切换到使用保留属性将使您免于所有这些麻烦。您正在泄漏以前的NSArray分配,因为在代码的这一部分:
NSDictionary *resultsDictionary = [responseString objectFromJSONString];
jokesArray = [resultsDictionary allValues];
[jokesArray retain];
您正在创建一个NSDictionary,并替换JokeArray指向您刚刚创建的NSDictionary中的数据的任何内容。
另外,NSDictionary返回的数据是使用一种方便的初始化方法创建的,这意味着它将在一段时间后被释放,因此您需要保留它
由于您直接修改了jokesArray变量,因此在使用新对象替换之前分配的NSArray时,不会释放它。您是如何声明jokesArray的?不完全正确。NSDictionary的allValues返回NSArray*。jokesArry被设置为allValues创建的NSArray(正如您所说,它将在没有保留的情况下自动释放)@Grabunks我想你误解了什么。他没有访问某个属性。他直接将它分配给变量,这样jokesArray指向的任何内容都将丢失,从而留下以前分配给leak的NSArray。但是编辑了措辞,这样会更清楚。当然,你是对的;我只是说这是一个NSArray而不是NSDictionary。从字典中获取的当前对象的保留不会使其泄漏。下次调用viewDidUnload时,它将释放最后一个保留的对象。泄漏的是您在ViewDidLoad中分配的NSArray。这是代码的总体解决方案。删除以下内容viewDidLoad中的wing代码:jokesArray=[[NSArray alloc]init];
并且不会再泄漏任何内容。此外,在将其分配给新对象之前,我会向jokesArray发送一个释放,以防将来调用getjonks