Objective c 有人能给我解释一下为什么我;“需要”;以下代码段中的retain语句?

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

我相信在整个过程中学习,下面的代码段对我来说不是很清楚。我知道alloc语句会增加retain计数,但是iOS开发的某些方面仍然让我感到非常困惑

为什么我需要一个:
[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