AFNetworking EXC_BAD_ACCESS (code=2, address=0x0) in downloadTask
Posted
技术标签:
【中文标题】AFNetworking EXC_BAD_ACCESS (code=2, address=0x0) in downloadTask【英文标题】: 【发布时间】:2014-03-20 03:49:54 【问题描述】:我有一个应用程序,它在登录后为客户编译客户特定报告列表。这些报告正在显示,我已经放置了一个“查看”按钮,该按钮应该下载 PDF 文件,并在应用程序中显示它。
在这个阶段,按下查看按钮时似乎出现了内存问题,我不知道如何找到问题所在。这是我的代码:
#import "reportsTestViewController.h"
#import "ReportsDataObject.h"
#import "Session.h"
#import "AFNetworking.h"
@interface reportsTestViewController ()
@end
@implementation reportsTestViewController
@synthesize response;
@synthesize myDataIvar;
@synthesize viewReportPressed;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
reportsTable.delegate = self;
reportsTable.dataSource = self;
self.sections = [[NSMutableDictionary alloc] init];
[super viewDidLoad];
- (void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
#pragma mark NSURLConnection Delegate Methods
//
//Create your request pointing to the test page
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.tesg.com.au/allCustBuild.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//initialize it when you create your connection
if (connection)
self.myDataIvar = [[NSMutableData alloc] init];
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
[self.myDataIvar setLength:0];
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
[self.myDataIvar appendData:data];
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
NSLog(@"Connection Failed: %@", error.userInfo);
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
//this is where you would parse the data received back from the server
NSString *responseString = [[NSString alloc] initWithData:self.myDataIvar encoding:NSUTF8StringEncoding];
NSLog(@"Received Data: %@",responseString);
[self setupReportsFromJSONArray:self.myDataIvar];
-(void)connectionWasASuccess:(NSData *)data
[self setupReportsFromJSONArray:data];
-(void)setupReportsFromJSONArray:(NSData*)dataFromReportsArray
BOOL found;
NSError *error;
// NSMutableArray *reportsArray = [[NSMutableArray alloc] init];
NSArray *arrayFromServer = [NSJSONSerialization JSONObjectWithData:dataFromReportsArray options:0 error:&error];
if(error)
NSLog(@"error parsing the json data from server with error description - %@", [error localizedDescription]);
else
reportsArray = [[NSMutableArray alloc] init];
for(NSDictionary *eachReport in arrayFromServer)
ReportsDataObject *report = [[ReportsDataObject alloc] initWithJSONData:eachReport];
[reportsArray addObject:report];
NSString *c = [[eachReport objectForKey:@"title"] substringToIndex:3];
found = NO;
for (NSString *str in [self.sections allKeys])
if ([str isEqualToString:c])
found = YES;
if (!found)
[self.sections setValue:[[NSMutableArray alloc] init] forKey:c];
NSLog(@"Array Populated");
NSLog(@"%u reports found",reportsArray.count);
//Now you have your reportsArray filled up with all your data objects
for (NSDictionary *eachReport in arrayFromServer)
[[self.sections objectForKey:[[eachReport objectForKey:@"title"] substringToIndex:3]] addObject:eachReport];
// Sort each section array
for (NSString *key in [self.sections allKeys])
[[self.sections objectForKey:key] sortUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"title" ascending:YES]]];
[reportsTable reloadData];
-(void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
-(void)viewReportPressed:(UIButton*)button
NSLog(@"Button successfully Pressed");
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://tesg.com.au/portal/media/reports/1367365180_367 Collins Passive April 2013.pdf"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *theResponse)
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[theResponse suggestedFilename]];
completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error)
NSLog(@"File downloaded to: %@", filePath);
];
[downloadTask resume];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
NSUInteger count = [[self.sections allKeys] count];
NSLog(@"Number of sections: %d", count);
return count;
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
return [[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:section];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
//We check against table to make sure we are displaying the right number of cells
// for the appropriate table. This is so that things will work even if one day you
//decide that you want to have two tables instead of one.
NSUInteger count = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:section]] count];
NSLog(@"Number of rows in section: %d", count);
return count;
//- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
//return [[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
//
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"Cell";
UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
//The beauty of this is that you have all your data in one object and grab WHATEVER you like
//This way in the future you can add another field without doing much.
NSUInteger count = [[self.sections allKeys] count];
if(count == 0)
cell.textLabel.text = @"no reports to show";
else
NSDictionary *Reports = [[self.sections valueForKey:[[[self.sections allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = [Reports objectForKey:@"title"];
cell.detailTextLabel.text = [Reports objectForKey:@"building"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:@selector(viewReportPressed:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"View" forState:UIControlStateNormal];
button.frame = CGRectMake(180.0f, 5.0f, 150.0f, 30.0f);
[cell addSubview:button];
// in the future you can grab whatever data you need like this
//[currentReport buildingName], or [currentReport reportName];
return(cell);
@end
当在任何单元格中按下视图按钮时,我得到 NSLog 说“按钮已成功按下”,但它在出现错误后立即崩溃
[downloadTask resume]; Thread 1:EXC_BAD_ACCESS (code=2, address=0x0)
任何想法如何解决这个问题?
【问题讨论】:
保留异常断点,以便找到问题的根源。 我有一个异常断点,但它似乎没有做任何事情。它仍然出现此错误 似乎崩溃发生在线程 1 的 [reportsTestViewController viewReportPressed:] 但我找不到原因。找出问题的最佳方法是什么? 在 [NSObject performSelector:withObject:withObject:] 下显示了一个问题 很好的总结,感谢您的帮助!我会牢记这一点:-) 【参考方案1】:如果您得到地址为0x0
的EXC_BAD_ACCESS
,这通常意味着在不允许nil
的上下文中使用了nil
值。
在这种情况下,这是因为您的 URL 字符串无效。不允许有空格。因此,您得到的URL
变量是nil
,这将导致您描述的行为。您可能希望对 URL 字符串进行百分比转义,例如:
NSString *URLString = @"http://tesg.com.au/portal/media/reports/1367365180_367 Collins Passive April 2013.pdf";
NSURL *URL = [NSURL URLWithString:[URLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
要在将来识别此类异常,您可以使用exception breakpoints,这通常有助于识别有问题的代码行。或者只是仔细检查您的代码代码,看看您可能无意中将 nil
值传递给了不接受它的方法。
但是,如果您得到的EXC_BAD_ACCESS
的值不是0x0
,这通常是由于尝试使用以前释放的对象而导致的。 (并非总是如此,但经常发生。幸运的是,ARC 使此类问题变得不那么常见。)显然,这里不是这种情况,但您询问如何识别您尝试使用以前释放的对象的情况。
要诊断这种情况,您通常会打开“僵尸”(请参阅Running Your Application with Diagnostics)。顺便说一句,一旦完成对僵尸的诊断,请确保将其关闭,因为您不想让僵尸保持开启状态(尤其是在生产应用中)。
无论如何,在这种情况下,因为地址是0x0
,所以它不是释放对象的结果,而是问题是由于无效的 URL 导致的 nil
值的错误使用。
【讨论】:
您好,谢谢您的回复。晚饭后我会继续做这个,让你知道我的进展!以上是关于AFNetworking EXC_BAD_ACCESS (code=2, address=0x0) in downloadTask的主要内容,如果未能解决你的问题,请参考以下文章
如何在旧的 AFNetworking 中使用 AFNetworking 2.0+?
无法识别的选择器发送到 UIButton+AFNetworking.h 的实例(UIImageView+AFNetworking 也是)