2011-10-10 65 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的其他引用(例如计数调用)有一些内存可供采取行动。

切换到使用保留属性将使您免于所有这些麻烦。

相关问题