Opening a pdf inside the app breaks the design - iphone

I'm having some kind of problems with one thing, i'm making an app and i have a webview that shows a pdf file, and i have a button if clicked will call an UIDocumentInteractionController (open the pdf in a new window).
I will leave screenshots to make it easier:
When i open the app:
http://imgur.com/dpIEd
After i open the UIDocumentInteractionController:
http://imgur.com/VYV2N
Here's the code too
.h file
#interface pdfView : UIViewController <UIDocumentInteractionControllerDelegate>
{
IBOutlet UIActivityIndicatorView *loading;
IBOutlet UIWebView *Wview;
UIDocumentInteractionController *controller;
}
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *loading;
#property (nonatomic, retain) IBOutlet UIWebView *Wview;
#property (nonatomic, retain) UIDocumentInteractionController *controller;
-(void)buttonPressed;
-(IBAction)open_in:(id)sender;
-(IBAction)back:(id)sender;
#end
.m file
#import "pdfView.h"
#implementation pdfView
#synthesize loading,Wview;
#synthesize controller;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void)viewDidLoad
{
[loading startAnimating];
[super viewDidLoad];
Wview.scalesPageToFit = TRUE;
Wview.multipleTouchEnabled = TRUE;
[Wview setOpaque:NO];
NSString *path = [[NSBundle mainBundle] pathForResource:#"guia_seguranca_2" ofType:#"pdf"];
NSURL *targetURL = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[Wview loadRequest:request];
[loading stopAnimating];
}
-(IBAction)open_in:(id)sender
{
NSString *fileToOpen = [[NSBundle mainBundle] pathForResource:#"guia_seguranca_2" ofType:#"pdf"];
UIDocumentInteractionController* preview = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:fileToOpen]];
preview.delegate = self;
[preview presentPreviewAnimated:YES];
[preview retain];
}
-(IBAction)back:(id)sender
{
[self.view removeFromSuperview];
}
-(void)buttonPressed
{
//[self.view removeFromSuperview];
NSString *fileToOpen = [[NSBundle mainBundle] pathForResource:#"guia_seguranca_2" ofType:#"pdf"];
UIDocumentInteractionController* preview = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:fileToOpen]];
preview.delegate = self;
[preview presentPreviewAnimated:YES];
[preview retain];
}
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
return self.view;
}
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
return self.view.frame;
}
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
[self.controller autorelease];
}
- (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.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc
{
[super dealloc];
[Wview release];
[loading release];
}
#end
Thanks in advance.....

I would suggest not useing the webview and using a pdf app (ibook, cloudreader) like this.
//name of pdf
NSString * pathString = #"userguide";
//get pdf path
NSString * filePath = [[NSBundle mainBundle] pathForResource:pathString ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:filePath];
self.docController = [UIDocumentInteractionController interactionControllerWithURL:url];
BOOL isValid = [self.docController presentOpenInMenuFromRect:self.handBookLaunch.frame inView:self.view animated:YES];
if (!isValid) {
NSString * messageString = [NSString stringWithFormat:#"No PDF reader was found on your device. Please download a PDF reader (eg. iBooks)."];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:messageString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];

Solved, added this code for layout verification:
-(void) viewWillAppear:(BOOL)animated
{
CGRect arect=[[UIScreen mainScreen]applicationFrame];
CGRect anotherrect=[[UIApplication sharedApplication]statusBarFrame];
if(self.view.center.y==arect.size.height/2)
self.view.center=CGPointMake(self.view.center.x, self.view.center.y+anotherrect.size.height); // fix silliness in IB that makes view start 20 pixels higher than it should on iPhone
}
source: https://discussions.apple.com/thread/2658315?start=0&tstart=0

Related

Pass string from UITableView to UIView in iOS

I want to pass 2 string selected from UITableview (CompleteView) to new UIView (DetailView)
This is my code:
In CompleteView.h()
#property (nonatomic, retain) NSString *memoString;
#property (nonatomic, retain) NSString *previewString;
In Completeview.m()
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
previewString = [PreviewArray objectAtIndex:indexPath.row];
NSLog(#"Preview string %#",previewString);
memoString = [MemoArray objectAtIndex:indexPath.row];
NSLog(#"Memo string %#",memoString);
DetailView *detailAlert = [[DetailView alloc] initWithFrame:CGRectMake(10, 40, 300, 300)];
detailAlert.strPreview =previewString ;
detailAlert.strMemo = memoString;
[self.view addSubview:detailAlert];
[detailAlert show];
[detailAlert release];
}
In DetailView()
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
originalFrame = frame;
UIWebView *videoview = [[UIWebView alloc] initWithFrame:CGRectMake(10,80,275.0,150)];
NSString *url=[NSURL URLWithString:strPreview];
NSURL *nsurl=[NSURL URLWithString:url];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[videoview loadRequest:nsrequest];
[self addSubview:videoview];
return self;
}
In DetailView.h
#property (nonatomic, retain) NSString* strMemo;
#property (nonatomic, retain) NSString* strPreview;
When run, previewString not send to DetailView. I'm debug, when run strPreview and strMemo in DetailView is 0x00000. Thanks in advance
You can pass custom Initialisers like below . If you wish you can add one parameter
to custom Initialisers
In CompleteView.h()
#property (nonatomic, retain) NSString *memoString;
#property (nonatomic, retain) NSString *previewString;
In Completeview.m()
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
previewString = [PreviewArray objectAtIndex:indexPath.row];
NSLog(#"Preview string %#",previewString);
memoString = [MemoArray objectAtIndex:indexPath.row];
NSLog(#"Memo string %#",memoString);
DetailView *detailAlert = [[DetailView alloc] initWithFrame:CGRectMake(10, 40, 300, 300) andPreviewstring:previewString];
detailAlert.strPreview =previewString ;
detailAlert.strMemo = memoString;
[self.view addSubview:detailAlert];
[detailAlert show];
[detailAlert release];
}
In DetailView()
- (id)initWithFrame:(CGRect)frame andPreviewstring:(NSString *)stPreview
{
self = [super initWithFrame:frame];
if (self) {
originalFrame = frame;
UIWebView *videoview = [[UIWebView alloc] initWithFrame:CGRectMake(10,80,275.0,150)];
NSString *url=[NSURL URLWithString:strPreview];
NSURL *nsurl=[NSURL URLWithString:url];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[videoview loadRequest:nsrequest];
[self addSubview:videoview];
return self;
}
In DetailView.h
#property (nonatomic, retain) NSString* strMemo;
#property (nonatomic, retain) NSString* strPreview;
- (id)initWithFrame:(CGRect)frame andPreviewstring:(NSString *)stPreview;
try this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
previewString = [PreviewArray objectAtIndex:indexPath.row];
NSLog(#"Preview string %#",previewString);
memoString = [MemoArray objectAtIndex:indexPath.row];
NSLog(#"Memo string %#",memoString);
DetailView *detailAlert = [[DetailView alloc] initWithFrame:CGRectMake(10, 40, 300, 300)];
detailAlert.strPreview =previewString ;
detailAlert.strMemo = memoString;
[detailAlert createWebView];
[self.view addSubview:detailAlert];
[detailAlert show];
[detailAlert release];
}
write code for string allocation
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
originalFrame = frame;
//add following two lines
strPreview = [[NSString alloc] init];
strMemo = [[NSString alloc] init];
//........
return self;
}
-(void) createWebView {
UIWebView *videoview = [[UIWebView alloc] initWithFrame:CGRectMake(10,80,275.0,150)];
NSString *url=[NSURL URLWithString:strPreview];
NSURL *nsurl=[NSURL URLWithString:url];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[videoview loadRequest:nsrequest];
[self addSubview:videoview];
}
The problem here is you are setting two properties in detail view after initializing DetailView. But you are trying to use a property values within the initializer which are yet to be set.
As I can see there are two options you can try out.
Write another initializer which accept these two properties. So that you can use those two properties in that initializer.
(id)initWithFrame:(CGRect)frame strMemo:(NSString *)memo strPreview:(NSString *)preview {
self = [super initWithFrame:frame];
if (self) {
originalFrame = frame;
UIWebView *videoview = [[UIWebView alloc] initWithFrame:CGRectMake(10,80,275.0,150)];
NSString *url=[NSURL URLWithString:preview];
NSURL *nsurl=[NSURL URLWithString:url];
NSURLRequest *nsrequest=[NSURLRequest requestWithURL:nsurl];
[videoview loadRequest:nsrequest];
[self addSubview:videoview];
return self;
}
Or else you can extract the logic in the current initializer and put them in to a separate method which you can called after setting two properties from the CompleteView.

Can't write in a .plist

I have a little app that have by default youtube as homepage. You can change it in a little menu, but it doesn't work and I don't know why.
Here's the code
viewController
.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UIWebView *webView;
}
#property (retain, nonatomic) NSArray *array;
#property (retain, nonatomic) NSString *string1;
-(NSString *) dataFilePath;
- (IBAction)settings:(id)sender;
- (IBAction)home:(id)sender;
#end
.m
#import "ViewController.h"
#import "settings.h"
#implementation ViewController
#synthesize array;
#synthesize string1;
- (void)viewDidLoad
{
[super viewDidLoad];
if ([string1 isEqual:#"youtube"]) {
NSMutableArray *Array = [[NSMutableArray alloc] init];
[Array addObject:#"http://www.youtube.com"];
[Array writeToFile:[self dataFilePath] atomically:YES];
}
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
array = [[NSArray alloc] initWithContentsOfFile:filePath];
}
NSString *string = [NSString stringWithString:[array objectAtIndex:0]];
[webView loadRequest:[[NSURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:string]]];
}
-(NSString *) dataFilePath
{
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [path objectAtIndex:0];
return [documentDirectory stringByAppendingPathComponent:#"url.plist"];
string1 = #"youtube";
}
- (IBAction)settings:(id)sender {
settings *NView = [[settings alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:NView animated:YES];
}
- (IBAction)home:(id)sender {
NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
array = [[NSArray alloc] initWithContentsOfFile:filePath];
}
NSString *string = [NSString stringWithString:[array objectAtIndex:0]];
NSLog(#"%#\n",string);
[webView loadRequest:[[NSURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:string]]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
Settings //here's the menu where I can change the homepage
.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface settings : UIViewController{
ViewController *viewCont;
IBOutlet UITextField *field;
}
-(IBAction)back:(id)sender;
- (IBAction)setHP:(id)sender;
#end
.m
#import "settings.h"
#import "ViewController.h"
#implementation settings
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib
}
- (void)viewDidUnload
{
field = nil;
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(IBAction)back:(id)sender{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)setHP:(id)sender {
NSMutableArray *Array = [[NSMutableArray alloc] init];
[Array addObject:field.text];
[Array writeToFile:[viewCont dataFilePath] atomically:YES];
[viewCont.string1 initWithString:#"other" ];
NSLog(#"%#\n", viewCont.string1);// HERE XCODE SAYS string1 = null!!! WHY?
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
So anyone knows what am I doing wrong? Please help me, I have searched around the web for 4 days and I didn't find anything!
I don't understand well your problem but i notice that you are not initializing viewCont in the setHP: action.
try to add this line:
ViewController *viewCont=[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
just before
[viewCont.string1 initWithString:#"other" ];

Able to touch the background of activity indicator

In my iphone application an activity indicator is shown at the time of webservice call. My problem is that i am able to touch the view on which the activity indicator is shown.My view has textfields and buttons and i am able to enter values in the text fields and also change the button states while the activity indicator is still on it. Have anybody faced a similar situation? Does anybody know a solution to this problem? All helpful suggestions are welcomed.
Here is my activity indicator class.
ActivityProgressViewController.h
#import <UIKit/UIKit.h>
#interface ActivityProgressViewController : UIViewController {
IBOutlet UIActivityIndicatorView *_activityIndicator;
IBOutlet UILabel *_labelMessage;
NSString *_messageToShow;
}
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;
#property (nonatomic, retain) IBOutlet UILabel *labelMessage;
+ (ActivityProgressViewController*) createInstance;
- (void)show;
- (void)showWithMessage:(NSString*)message;
- (void)close;
+ (void)show;
+ (void)close;
#end
ActivityProgressViewController.m
#import "ActivityProgressViewController.h"
#define kACTIVITY_INDICATOR_NIB #"ActivityProgressViewController"
#implementation ActivityProgressViewController
#synthesize activityIndicator = _activityIndicator;
#synthesize labelMessage = _labelMessage;
static ActivityProgressViewController *_viewController;
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
}
- (void)viewDidLoad {
if (_messageToShow) _labelMessage.text = _messageToShow;
}
- (void)dealloc {
[_labelMessage release];
[_messageToShow release];
[_activityIndicator release];
[super dealloc];
}
+ (ActivityProgressViewController*) createInstance {
_viewController = [[ActivityProgressViewController alloc] initWithNibName:kACTIVITY_INDICATOR_NIB bundle:nil];
return _viewController;
}
- (void)show
{
[_activityIndicator startAnimating];
UIWindow *window = [[[UIApplication sharedApplication] windows]objectAtIndex:0];
NSLog(#"[[UIApplication sharedApplication] windows]===%#",[[UIApplication sharedApplication] windows]);
self.view.frame = CGRectMake(window.bounds.origin.x, window.bounds.origin.y, window.bounds.size.width, window.bounds.size.height);
[window addSubview:self.view];
}
- (void)showWithMessage:(NSString*)message {
_messageToShow = message;
[self show];
}
- (void)close
{
[self.view removeFromSuperview];
}
+ (void)show {
if (!_viewController) {
_viewController = [ActivityProgressViewController createInstance];
}
[_viewController show];
}
+ (void)close {
if (_viewController) {
[_viewController close];
}
}
#end
Here is how i call from my required class.
[ActivityProgressViewController show];
[ActivityProgressViewController close];
I also call the activity indicator while exporting audio.
This is the code I use for exporting
-(void)exportAudioFile:(AVComposition*)combinedComposition
{
[ActivityProgressViewController show];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:combinedComposition
presetName:AVAssetExportPresetPassthrough];
NSArray *presets =[AVAssetExportSession exportPresetsCompatibleWithAsset:combinedComposition];
NSLog(#"presets======%#",presets);
NSLog (#"can export: %#", exportSession.supportedFileTypes);
NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [dirs objectAtIndex:0];
exportPath = [documentsDirectoryPath stringByAppendingPathComponent:#"CombinedNew.m4a"];
[[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
exportURL = [NSURL fileURLWithPath:exportPath];
exportSession.outputURL = exportURL;
exportSession.outputFileType = #"com.apple.m4a-audio";
exportSession.shouldOptimizeForNetworkUse = YES;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
NSLog (#"i is in your block, exportin. status is %d",
exportSession.status);
switch (exportSession.status)
{
case AVAssetExportSessionStatusFailed:
{
break;
}
case AVAssetExportSessionStatusCompleted:
{
exportSuccess = YES;
if (recorderFilePath)
{
NSError *finalurlError;
[[NSFileManager defaultManager]removeItemAtPath:recorderFilePath error:&finalurlError];
finalurlError = nil;
[[NSFileManager defaultManager]copyItemAtPath:[exportURL path] toPath:recorderFilePath error:&finalurlError];
NSLog(#"finalurlError 2-----%#",finalurlError);
}
[ActivityProgressViewController close];
fileUrl = [NSURL fileURLWithPath:recorderFilePath];
[self updatePlayerForUrl:fileUrl];
break;
}
case AVAssetExportSessionStatusUnknown:
{
break;
}
case AVAssetExportSessionStatusExporting:
{
break;
}
case AVAssetExportSessionStatusCancelled:
{
break;
}
case AVAssetExportSessionStatusWaiting:
{
break;
}
default:
{
NSLog (#"didn't get export status");
break;
}
};
}];
[exportSession release];
}
You're adding your activity indicator to the middle of another view, yes?
If so, you can do this in your show method:
self.superview.userInteractionEnabled = NO;
And in your close method:
self.superview.userInteractionEnabled = YES;
Here is where you'll find information on the UIView's userInteractionEnabled property: http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instp/UIView/userInteractionEnabled
Hope this helps!

I am Getting EXC_BAD_ACCESS while NSURLREQUEST

I am getting EXC_BAD_ACCESS while NSURLREQUEST.
I am giving pdf url from server to to webview through AppDelegate_iPhone's currentBookPressed.
please can anyone tell what is the problem ...
Code:-
#class AppDelegate_iPhone;
#interface PdfShowViewController : UIViewController<UIWebViewDelegate> {
UIWebView *pdfWebview;
AppDelegate_iPhone *appDelegate;
NSMutableData *receivedData;
UIActivityIndicatorView *myIndicator;
IBOutlet UIProgressView *progress;
NSURLRequest* DownloadRequest;
NSURLConnection* DownloadConnection;
long long bytesReceived;
long long expectedBytes;
}
#property (nonatomic,retain) UIWebView *pdfWebview;
#property (nonatomic,retain) UIActivityIndicatorView *myIndicator;
#property (nonatomic,retain) IBOutlet UIProgressView *progress;
#property (nonatomic,retain) NSMutableData *receivedData;
#property (nonatomic, readonly, retain) NSURLRequest* DownloadRequest;
#property (nonatomic, readonly, retain) NSURLConnection* DownloadConnection;
-(IBAction)onTapBack;
#end
#import "PdfShowViewController.h"
#import "AppDelegate_iPhone.h"
#implementation PdfShowViewController
#synthesize pdfWebview,myIndicator,progress,receivedData,DownloadRequest,DownloadConnection;
- (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];
pdfWebview = [[UIWebView alloc] initWithFrame:CGRectMake(0, 40, 320, 420)];
[pdfWebview setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[pdfWebview setScalesPageToFit:YES];
[pdfWebview setAutoresizesSubviews:YES];
[pdfWebview loadRequest:DownloadRequest];
[self.view addSubview:pdfWebview];
//[connection release];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
myIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
myIndicator.center = self.view.center;
myIndicator.hidesWhenStopped = NO;
[self.view addSubview:myIndicator];
[myIndicator startAnimating];
//receivedData = [[NSMutableData alloc] initWithLength:0];
NSLog(#"%#",appDelegate.currentBookPressed);
NSString * urlString = [appDelegate.currentBookPressed stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSLog(#"%#",urlString);
NSURL *targetURL = [NSURL URLWithString:urlString];
NSLog(#"%#",targetURL);
// Here comes Acception
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
DownloadConnection = [[NSURLConnection alloc] initWithRequest:DownloadRequest delegate:self];
if (DownloadConnection) {
receivedData = [[[NSMutableData data]initWithLength:0]retain];
}
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
-(IBAction)onTapBack
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)dealloc {
[super dealloc];
[pdfWebview release];
[receivedData release];
}
#end
You should replace line
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
with line
DownloadRequest = [NSURLRequest requestWithURL:targetURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
It is because method requestWithURL:cachePolicy:timeoutInterval: in first parameter is waiting for object of NSURL class. In targerURL you have exactly that one.
Moreover in method [NSURL URLWithString:targetURL] (if you will need it) you should pass NSString as a first parameter, but you are passing NSURL.
Your problem in this line
DownloadRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:targetURL] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:120.0];
The problem in your case arises because parameter for + (id)URLWithString:(NSString *)URLString is NSString and you are passing NSURL and method trying to get the length of the supposed string by calling -length, which exists for NSString but not for NSURL.

How to load table with some default image till it get the original image from internet iPhone?

I have a uitableview which stores one image in one cell. Its image get loaded from internet. The problem is the application get slow till its image get loaded from internet. So I want to put a mechanism that it first get loaded with a default image and when it gets the original then the default image will be replaced by the original one.
Give me any tutorial or any sample code for it.
Thanks in advance.
Get your image trough some other thread .... and use notification or delegate to keep track of any change in image download ... suppose you are using notification .... then in class which you set as observer for that notification reload the data of tableView .... so your table image will get updated where there was so default image .... for more detail lets take an example ..... Make a operation class to downloading the image we call it thumb .... In this example I make 2 classes
1. PhotoGalleryVC which shows a list of thumbs and some detail of each thumb and
2. LoadGalleryThumbOp [Op = operation] downloads thumbs and post notification when done
#protocol LoadGalleryThumbDelegate;
#interface LoadGalleryThumbOp : NSObject{
NSIndexPath* indexPathInTableView;
id <LoadGalleryThumbDelegate> delegate;
NSMutableData *activeDownload;
NSURLConnection *imageConnection;
NSString * documentPath;
BOOL imageDownload;
}
#property (nonatomic, assign) NSIndexPath* indexPathInTableView;
#property (nonatomic, retain) NSMutableData *activeDownload;
#property (nonatomic, retain) NSURLConnection *imageConnection;
#property (nonatomic, assign) id <LoadGalleryThumbDelegate> delegate;
#property (nonatomic, retain) NSString * documentPath;
#property (nonatomic) BOOL imageDownload;
- (void)startDownload;
- (void)cancelDownload;
- (void) persistData:(NSData*) data;
#end
#protocol LoadGalleryThumbDelegate
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
in LoadGalleryThumbOp.m do it as
#implementation LoadGalleryThumbOp
#synthesize year;
#synthesize indexPathInTableView;
#synthesize delegate;
#synthesize activeDownload;
#synthesize imageConnection,documentPath,imageDownload;
#pragma mark
- (void)startDownload
{
self.imageDownload = YES;
self.activeDownload = [NSMutableData data];
NSFileManager* fm = [NSFileManager defaultManager];
NSString* galleryDocumentPath = [self.documentPath stringByAppendingPathComponent:[NSString stringWithFormat:#"images/thumb.jpg"]];
if ([fm fileExistsAtPath:galleryDocumentPath])
{
UIImage *image = [[UIImage alloc] initWithContentsOfFile:galleryDocumentPath ];
self.gallery.thumpImage = image;
self.activeDownload = nil;
[image release];
self.imageConnection = nil;
[delegate appImageDidLoad:self.indexPathInTableView];
}
else {
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:#error yourImageUrl]] delegate:self];
self.imageConnection = conn;
[conn release];
}
}
- (void)cancelDownload
{
[self.imageConnection cancel];
self.imageConnection = nil;
self.activeDownload = nil;
}
#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.activeDownload appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
self.activeDownload = nil;
self.imageConnection = nil;
self.imageDownload = NO;
[NSString stringWithFormat:#"images/thumb.jpg"]];
[delegate appImageDidLoad:self.indexPathInTableView];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self persistData:self.activeDownload];
self.activeDownload = nil;
self.imageConnection = nil;
[delegate appImageDidLoad:self.indexPathInTableView];
}
- (void) persistData:(NSData*) data
{
NSFileManager* fm = [NSFileManager defaultManager];
NSString* galleryDocumentPath = [self.documentPath stringByAppendingPathComponent:[NSString stringWithFormat:#"images/thumb.jpg"]];
if ([[NSFileManager defaultManager] fileExistsAtPath:galleryDocumentPath])
{
NSError* err = nil;
[fm removeItemAtPath:galleryDocumentPath error:&err];
if (err)
NSLog(#"%s:%#",__FUNCTION__,err);
}
[fm createFileAtPath:galleryDocumentPath contents:data attributes:nil];
}
this class will download the image you wanted and will call its delegate when the image is download ..
Now comes its use part in PhotoGalleryVC use it like this
#interface PhotoGalleryVC : UIViewController <LoadGalleryThumbDelegate>{
IBOutlet UITableView* albumListTableView;
NSMutableDictionary *imageDownloadsInProgress;
NSArray* allThumbs;
}
#property (nonatomic, retain) NSMutableDictionary *imageDownloadsInProgress;
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
in .m part
- (void)viewDidLoad {
self.imageDownloadsInProgress = [NSMutableDictionary dictionary];
.....
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSFileManager* fm = [NSFileManager defaultManager];
NSString* galleryDocumentPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"Gallery/%#/images/thumb.jpg",[someObj.title stringByReplacingOccurrencesOfString:#" " withString:#"_" ]]];
//this above line is just make a seperate folder for each object and store thumbs of that object in that folder ... so make it unique some how
if (![fm fileExistsAtPath:galleryDocumentPath])
{
LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (galleryThumbDownloader != nil && galleryThumbDownloader.imageDownload == NO)
{
[cell.activityIndicator stopAnimating];
cell.albumCoverImageView.image = [UIImage imageNamed:#"no_thumb.png"];
}
else {
[cell.activityIndicator startAnimating];
}
[self startIconDownload:temp forIndexPath:indexPath andYear:[NSString stringWithFormat:#"%d",selectedYear]];
}
else
{
[cell.activityIndicator stopAnimating];
cell.albumCoverImageView.image = [UIImage imageWithContentsOfFile:galleryDocumentPath];
}
return cell ;
}
//The following method see if there is already so downloader that is downloading same image then it simply do nothing else it create a downloader and start it
- (void)startIconDownload:(Gallery *)gallery forIndexPath:(NSIndexPath *)indexPath andYear:(NSString*)yr
{
LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (galleryThumbDownloader == nil)
{
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* nameWithoutSpace = [gallery.title stringByReplacingOccurrencesOfString:#" " withString:#"_" ];
NSString* galleryDocumentPath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"Gallery//%#",nameWithoutSpace]];
galleryThumbDownloader = [[LoadGalleryThumbOp alloc] init];
galleryThumbDownloader.documentPath = galleryDocumentPath;
galleryThumbDownloader.indexPathInTableView = indexPath;
galleryThumbDownloader.delegate = self;
[imageDownloadsInProgress setObject:galleryThumbDownloader forKey:indexPath];
[galleryThumbDownloader startDownload];
[galleryThumbDownloader release];
}
else if(galleryThumbDownloader.imageDownload == NO)
{
if (albumListTableView.dragging || albumListTableView.decelerating) {
[galleryThumbDownloader startDownload];
}
}
}
finally the method which is called when a particular image is downloaded
- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
CustomCellPhotoGalary* cell = (CustomCellPhotoGalary*)[albumListTableView cellForRowAtIndexPath:indexPath];
LoadGalleryThumbOp *galleryThumbDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (galleryThumbDownloader != nil)
{
if (galleryThumbDownloader.imageDownload)
{
[cell.activityIndicator stopAnimating];
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* nameWithoutSpace = [temp.title stringByReplacingOccurrencesOfString:#" " withString:#"_" ];
NSString* galleryDocumentPath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"Gallery/%#",nameWithoutSpace]];
cell.albumCoverImageView.image = [UIImage imageWithContentsOfFile:galleryDocumentPath];
//galleryThumbDownloader = nil;
}
else {
[cell.activityIndicator stopAnimating];
cell.albumCoverImageView.image = [UIImage imageNamed:#"no_thumb.png"];
[self startIconDownload:temp forIndexPath:indexPath andYear:[NSString stringWithFormat:#"%d",selectedYear]];
}
[albumListTableView reloadData];
}
}
woooh.....! thats a lot of code for one example
Note : I cut out so many line so this code may not work for u directly {there may be so many errors .. }, But i hope you get the main idea behind the scene ... :)
This sample code is great, It taught me a lot.
This uses the ASIHttpRequest framework, if you are going to use this technique, I recommend you use the latest version from here, because the version in the sample code is quite old now.
This sample code should help you with custom delegation of your cells etc.
As per above scenario, its always better to use LazyTableImages.
The best example given here