Мое приложение падает при загрузке больших файлов PDF (> 2 МБ) в iphone - PullRequest
1 голос
/ 14 ноября 2011

Мое приложение работает нормально для загрузки небольших PDF-файлов и их отображения в WebView, но когда я получаю URL-адрес PDF-файлов размером более 2 МБ, оно каждый раз вылетает.

Код: -

@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.

Ответы [ 3 ]

1 голос
/ 14 ноября 2011

Первое, что вы выделяете, не освобождается (theconnection, alert, viewcontroller2)

second [connection release]; in - (void)connectionDidFinishLoading:(NSURLConnection *)connection, какое соединение вы освобождаете

после очистки этой проблемы, проверьте изапустить приложение.затем объясните, что является вашим исключением или ошибкой.

1 голос
/ 30 апреля 2013

вы, вероятно, превышаете ограничение в 30 МБ ОЗУ,

вы не должны использовать объект 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];

        }
    }
}
1 голос
/ 14 ноября 2011

Исходя из того, что вы говорите в своем комментарии (приложение падает на устройстве, но не на симуляторе) и учитывая, что вы загружаете большие файлы PDF, я предполагаю, что у вас возникают проблемы с памятью, и ваше приложение убиваетсясистема (обычно это связано с сообщением журнала об отправке сигнала 0 в приложение).

Если это так, я бы посоветовал вам сохранять загружаемые данные постепенно;т.е. вы не добавляете все данные в NSData и в самом конце (когда вы получили все данные) вы сохраняете их в файл.Вы можете добавлять в файл каждый полученный кусок и освобождать вашу память.

С другой стороны, я не очень хорошо понимаю, почему вы делаете это:

unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];

, поскольку выне используется byteBuffer в другом месте в методе connectionDidFinishLoading.Я думаю, что это не является причиной проблемы, поскольку локальная переменная освобождается после этого, но все же, если вы получаете большой кусок данных, вы дублируете его (один раз в NSData, второй раз в стеке).

Что касается проблемы с пространством в ваших URL, вам следует подумать о том, чтобы избежать их, используя

stringByAddingPercentEscapesUsingEncoding:

, который является NSString методом.

...