我的应用程序可以正常下载小Pdf并在WebView中显示它们,但是当我获取大小超过2 MB的pdf网址时,它每次都会崩溃。
代码: -
@implementation SecondViewController
@synthesize scrollView,receivedData,myIndicator;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
[myIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
myIndicator.hidesWhenStopped = YES;
[myIndicator startAnimating];
UIColor *background = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"iphone_landscape.png"]];
self.view.backgroundColor = background;
[background release];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://litofinter.es.milfoil.arvixe.com/displayxml1.aspx"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:150.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData = [[NSMutableData data] retain];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
int x=10,y=50;
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 45,320, 480)];
scrollView.contentSize = CGSizeMake(320,5000);
scrollView.showsVerticalScrollIndicator = YES;
for (Litofinter *lito in appDelegate.bookArray) {
if([appDelegate.currentButtonPressed isEqualToString:lito.cName])
{
NSLog(@"Count == %d ===",[lito.productsArray count]);
for (Products *prod in lito.productsArray) {
NSString * urlString = [prod.thumbnail stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSURL * imageURL = [NSURL URLWithString:urlString];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];
[myIndicator stopAnimating];
[myIndicator removeFromSuperview];
UIButton *imageButton = [[UIButton buttonWithType:UIButtonTypeCustom]retain];
[imageButton setFrame:CGRectMake(x, y, 140, 190)];
[imageButton setImage:image forState:UIControlStateNormal];
[imageButton setTitle:prod.pdf forState:UIControlStateNormal];
[imageButton addTarget:self action:@selector(onTapBook:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:imageButton];
x = x + 160;
if(x >300)
{
y = y +250;
x = 10;
}
}
}
}
[self.view addSubview:scrollView];
[connection release];
[receivedData release];
}
-(void)onTapBook:(id)sender{
UIButton *button = (UIButton *) sender;
appDelegate.currentBookPressed = [button currentTitle];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Ver Catalogo!" message:@"" delegate:self cancelButtonTitle:@"Cancelar" otherButtonTitles:@"Ver on-line",@"Descargar",nil];
[alert show];
}
// when I click on Descargar button i.e. download it goes to next PdfShowViewController
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:@"Ver on-line"])
{
viewController2 = [[PdfShowViewController alloc]initWithNibName:@"PdfShowViewController" bundle:nil];
[self presentModalViewController:viewController2 animated:YES];
}
else if([title isEqualToString:@"Descargar"])
{
viewController2 = [[PdfShowViewController alloc]initWithNibName:@"PdfShowViewController" bundle:nil];
[self presentModalViewController:viewController2 animated:YES];
}
}
-(IBAction)onTapBack{
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
[scrollView release];
}
@end
// here i am showing the pdf on a webView and downloading them
@implementation PdfShowViewController
@synthesize pdfWebview,myIndicator,progress,receivedData,DownloadRequest,DownloadConnection,downloadLabel,openURL;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
NSLog(@"Data === %ld",receivedData);
NSInteger receivedLen = [data length];
bytesReceived = (bytesReceived + receivedLen);
NSLog(@"received Bytes == %f",bytesReceived);
if(expectedBytes != NSURLResponseUnknownLength)
{
NSLog(@"Expected Bytes in if == %f",expectedBytes);
NSLog(@"received Bytes in if == %f",bytesReceived);
float value = ((float) (bytesReceived *100/expectedBytes))/100;
NSLog(@"Value == %f",value);
progress.progress=value;
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connection release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
expectedBytes = [response expectedContentLength];
NSLog(@"%f",expectedBytes);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[myIndicator stopAnimating];
[myIndicator removeFromSuperview];
[progress setHidden:YES];
[downloadLabel setHidden:YES];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:@"MayankPdf.pdf"];
unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
[self.receivedData writeToFile:pdfPath atomically:YES];
[connection release];
//Now create Request for the file that was saved in your documents folder
NSURL *url = [NSURL fileURLWithPath:pdfPath];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[pdfWebview setScalesPageToFit:YES];
[pdfWebview loadRequest:requestObj];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
[downloadLabel setText:@"Downloading..."];
[downloadLabel setHidden:NO];
[myIndicator setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
myIndicator.hidesWhenStopped = YES;
[myIndicator startAnimating];
NSLog(@"REquired --------------------------------%@",appDelegate.currentBookPressed);
// NSString *urlString = [appDelegate.currentBookPressed stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *urlString = [appDelegate.currentBookPressed stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"The Url Stirng=======%@",urlString);
NSURL *targetURL = [NSURL URLWithString:urlString];
NSLog(@"Trageted String ------======++++++++%@",targetURL);
DownloadRequest = [NSURLRequest requestWithURL:targetURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
DownloadConnection = [[NSURLConnection alloc] initWithRequest:DownloadRequest delegate:self];
if (DownloadConnection) {
receivedData = [[NSMutableData data]retain];
}
[pdfWebview setScalesPageToFit:YES];
// [pdfWebview loadRequest:DownloadRequest];
}
-(IBAction)onTapBack
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
[pdfWebview release];
// [receivedData release];
}
@end
我的解析器也不接受有空格的URL,任何解决方案都将受到赞赏。提前致谢
请原谅我写错了,因为我在Iphone上不是很好。
答案 0 :(得分:1)
根据您在评论中所说的内容(应用程序在设备上崩溃但未在模拟器上崩溃)并考虑到您正在下载大型PDF文件,我的猜测是您遇到内存问题并且您的应用程序被系统(这通常与关于发送给应用程序的信号0的日志消息相关联。)
如果是这样,我建议您逐步存储下载的数据;即,您不会在NSData
中附加所有数据,并且在最后(当您获得所有数据时)将它们存储到文件中。您可以将每个收到的块附加到文件中并释放内存。
另一方面,我不太清楚为什么要这样做:
unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
因为您未在byteBuffer
方法中的其他地方使用connectionDidFinishLoading
。我认为这不是问题的原因,因为此后局部变量被释放,但是如果你收到大量数据,你仍然会复制它(一次在NSData中,第二次在堆栈上)。
关于网址中的空间问题,您应该考虑使用
转义它们stringByAddingPercentEscapesUsingEncoding:
这是NSString
方法。
答案 1 :(得分:1)
你分配的大部分东西都没有被释放(连接,警报,视图控制器2)
[connection release];
中的第- (void)connectionDidFinishLoading:(NSURLConnection *)connection
个您要发布的连接
清除此问题后,请检查并运行该应用。然后解释你的异常或错误。
答案 2 :(得分:1)
你的RAM限制可能超过30MB,
您不应该使用NSMutableData对象来重建整个文件,而是直接将其写在“磁盘”上以限制内存使用。
激励你
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
@synchronized(connection) {
m_downloadedBytes += [data length];
CGFloat downloadProgress = ((CGFloat) m_downloadedBytes / (CGFloat) m_fileSize);
[self setDownloadProgress:downloadProgress];
if (!m_fileHandle) {
[data writeToURL:m_tmpTargetURL atomically:NO];
m_fileHandle = [[NSFileHandle fileHandleForWritingToURL:m_tmpTargetURL error:NULL] retain];
[m_fileHandle seekToEndOfFile];
}
else {
[m_fileHandle writeData:data];
}
}
}