MBProgressHud and SDWebImagePrefetcher - objective-c

I'm trying to show a custom MBProgressHUD while downloading a list of URLs with SDWebImagePrefetcher using NSURLConnection methods.
SDWebImagePrefetcher has a method that, when called, shows in console the progress of the images download.
Now, i would like to show that NSLog progress in the custom MBProgressHUD and I would like the HUD to stay on screen until the process is done, but I don't know how to do it and plus, when my NSURLConnection methods are called, it shows the initial HUD (Connnecting), then quickly jumps to "Complete", even if the images still needs to be downloaded.
Here's my code:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
HUD.mode = MBProgressHUDModeDeterminate;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
HUD.labelText = #"Loading";
HUD.detailsLabelText = #"Downloading contents..."; //here, i would like to show the progress of the download, but it seems to jump this part
HUD.dimBackground = YES;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//arr = array which holds a plist
NSMutableArray *array = [[[NSMutableArray alloc]init]autorelease];
for (NSDictionary *dict in arr) {
for (NSDictionary *val in [dict valueForKey:STR_ROWS]) {
[array addObject:[val objectForKey:#"image"]];
}
}
[prefetcher prefetchURLs:array];
HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"checkmark.png"]] autorelease];
HUD.mode = MBProgressHUDModeCustomView;
HUD.labelText = NSLocalizedString(#"Completed",#"Completed!");
HUD.detailsLabelText = nil;
HUD.dimBackground = YES;
[HUD hide:YES afterDelay:2];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[HUD hide:YES];
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Connection Failed message:[NSString stringWithFormat:#"Connection to the remote server failed with error:\n %#\n Try again in a while"),[error localizedDescription]] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alertView show];
}
I tried to look into the examples, but didn't find out how to do what i want to do.
EDIT
HUD Setup:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
[alertView dismissWithClickedButtonIndex:0 animated:YES];
}
else{
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus) {
case NotReachable:
{
//not reachable
break;
}
case (ReachableViaWWAN):
{
//reachable but not with the needed mode
break;
}
case (ReachableViaWiFi):{
HUD = [[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES]retain];
HUD.delegate = self;
HUD.dimBackground = YES;
HUD.labelText = #"Connecting...";
NSURL *URL = [NSURL URLWithString:#"http://mywebsite.com/myPlist.plist"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
[connection release];
break;
}
default:
break;
}
}
}
Any ideas?

In connection:didReceiveResponse: you must record how large the download is,
for example in self.responseSize. Then, in connection:didReceiveData: you
must append the data you just got to the data you previously got, and update the progress:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
HUD.mode = MBProgressHUDModeDeterminate;
HUD.labelText = #"Loading";
HUD.detailsLabelText = #"Downloading contents...";
HUD.dimBackground = YES;
// Define responseSize somewhere...
responseSize = [response expectedContentLength];
myData = [NSMutableData data];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[myData appendData:data];
HUD.progress = (float)myData.length / responseSize;
}

Related

connectiondidFinishLoading called twice

I am new to iphone development. I am able to use the data in connectiondidFinishLoading method.But i see "connection didfinishloading" method called twice.I don't know ,where i am going wrong. Here is my code
Edited code:
again connectionDidFinishLoading called twice
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField==CompanyName)
{
autocompleteTableView.hidden = NO;
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
if([CompanyName.text length]==0)
{
autocompleteTableView.hidden = YES;
[popoverController dismissPopoverAnimated:YES];
}
}
return YES;
}
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
data = [[NSMutableData alloc] init];
self.receivedData = data;
[data release];
NSURL *jsonUrl =[NSURL URLWithString:[NSString stringWithFormat:#"http://xxxx=%#",substring]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:jsonUrl];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self ];
//self.connection = connection;a
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
parser = [[NSXMLParser alloc] initWithData:receivedData];
currentHtmlElement=#"5";
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
[parser release];
if([arr4 count]!=0)
{
self.autocompleteUrls = [[[NSMutableArray alloc] init]autorelease];
UIViewController* popoverContent = [[UIViewController alloc] init]; //ViewController
self.autocompleteUrls = [[NSMutableArray alloc] init];
viewForautoCompleteTableView = [[UIView alloc]initWithFrame:CGRectMake (410, 120,270, 250)];
autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(0,0,270,250) style:UITableViewStyleGrouped];
autocompleteTableView.delegate = self;
autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.backgroundColor = [UIColor lightTextColor];
autocompleteTableView.rowHeight=28;
autocompleteTableView.backgroundView = nil;
autocompleteTableView.backgroundColor = [UIColor whiteColor];
autocompleteTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
[autocompleteTableView setSeparatorColor:[UIColor orangeColor]];
[viewForautoCompleteTableView setFrame:CGRectMake(210,380 ,autocompleteTableView.frame
.size.width
,autocompleteTableView.frame.size.height)];
[viewForautoCompleteTableView addSubview:autocompleteTableView];
[viewForautoCompleteTableView setBackgroundColor:[UIColor whiteColor]];
CGRect popoverFrame = viewForautoCompleteTableView.frame;
popoverContent.view = viewForautoCompleteTableView;
popoverController = [[UIPopoverController alloc] initWithContentViewController:popoverContent];
popoverController.delegate=self;
[popoverContent release];
[popoverController setPopoverContentSize:CGSizeMake(viewForautoCompleteTableView.frame.size.width, viewForautoCompleteTableView.frame.size.height) animated:NO];
[popoverController presentPopoverFromRect:popoverFrame inView:testscroll permittedArrowDirections:0 animated:YES];
[autocompleteUrls removeAllObjects];
for(int i=0;i<[arr4 count];i++)
{
NSString *curString = [[arr4 objectAtIndex:i] valueForKey:#"Name"];
[autocompleteUrls addObject:curString];
}
}
[autocompleteTableView reloadData];
[connection cancel];
}
you should remove [connection start]; because connection will start automatically after NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:selfstartImmediately:NO];
Edit
a valid NSURLConnection initialization
NSURLRequest *request =[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#""]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];

NSURLConnect works only 1 time

I'm trying to do a request but it works only in the first time....
Here is my code:
NSArray *infos = [rows objectAtIndex:indexPath.row];
NSString *thumbPath = thePath;
NSURLRequest *thumbRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:thumbPath]cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
self->thumbConnection = [[NSURLConnection alloc] initWithRequest:thumbRequest
delegate:self
startImmediately:YES];
self->thumbData = [[NSMutableData alloc]init];
when receive Response
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if (self->thumbData == nil) {
self->thumbData = [[NSMutableData alloc]init];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.thumbImage.image = [UIImage imageWithData:self->thumbData];
self.thumbActivityView.hidden = YES;
self->thumbData = nil;
}
when didFinishDownloading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.thumbImage.image = [UIImage imageWithData:self->thumbData];
self.thumbActivityView.hidden = YES;
[self->thumbData release];
self->thumbData = nil;
}
when timeout or other erros method:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self->thumbData release];
self->thumbData = nil;
self.thumbActivityView.hidden = YES;
[thumbConnection release];
self->thumbConnection = nil;
}
Don't allocate it again if it's non-nil. Better still allocate it in your object's init method and release it in your object's dealloc method

Loading and changing images asynchronous

Im loading 4 images from a website asynchronous,and after the loading i change them with a timer,but looks like on the array of the images is always the first image,when i change to another position of the array it contains the same image,dont change at all...
- (void)viewDidLoad
{
[super viewDidLoad];
[self getImages];
}
-(void)getImages
{
receivedData = [[NSMutableData alloc]init];
myImages = [[NSMutableArray alloc]init];
myImagesAdresses = [[NSMutableArray alloc]initWithCapacity:5];
[myImagesAdresses addObject:#"adress/Images/3.png"];
[myImagesAdresses addObject:#"adress/Images/2.png"];
[myImagesAdresses addObject:#"adress/Images/1.png"];
[myImagesAdresses addObject:#"adress/Images/0.png"];
[self loadNextImage];
}
-(void)loadNextImage
{
if([myImagesAdresses count])
{
NSURL * imageURL = [NSURL URLWithString:[myImagesAdresses lastObject]];
NSURLRequest * myRequest = [NSURLRequest requestWithURL:imageURL];
[[NSURLConnection alloc]initWithRequest:myRequest delegate:self];
NSLog(#"Start load URL %#",imageURL);
}
else {
[self.theImage setImage:[myImages objectAtIndex:2]];
[self changeImage];
NSLog(#"No More Images to Load");
}
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[myImages addObject:[UIImage imageWithData:[NSData dataWithData:receivedData]]];
[connection release];
connection = nil;
NSLog(#"Image from %# loaded",[myImagesAdresses lastObject]);
[myImagesAdresses removeLastObject];
[self loadNextImage];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[connection release];
connection =nil;
NSLog(#"Image from %# not loaded", [myImagesAdresses lastObject]);
[myImagesAdresses removeLastObject];
[self loadNextImage];
}
and the code to change the image:
-(void)changeImage
{
SEL selectorToCall = #selector(change: );
NSMethodSignature *methodSignature = [[self class] instanceMethodSignatureForSelector:selectorToCall];
NSInvocation * invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
[invocation setTarget:self];
[invocation setSelector:selectorToCall];
NSTimer * newTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 invocation:invocation repeats:YES];
self.paintingTimer = newTimer;
}
- (void) change:(NSTimer *)paramTimer
{
static NSInteger currentElement = 0;
if(++currentElement == [myImages count]) currentElement = 0;
[self.theImage setImage:[myImages objectAtIndex:currentElement]];
}
- (void) stopPainting
{
if (self.paintingTimer != nil){
[self.paintingTimer invalidate];
}
}
I dont getting any error,but the image simply dont change...
It looks like receivedData is an ivar that you repeatedly append to, but it never gets cleared. So after the first image is received, the second image is appended to it, etc.
After this line, you should empty receivedData:
[myImages addObject:[UIImage imageWithData:[NSData dataWithData:receivedData]]];
You should add this line of code after:
[myImages addObject:[UIImage imageWithData:[NSData dataWithData:receivedData]]];
like this:
[myImages addObject:[UIImage imageWithData:[NSData dataWithData:receivedData]]];
[receivedData setData:nil];

How can i get images from url which start from https instead of http?

I am using Lazy loading in my application.I want to Download images from url which starts from https i am not getting images using this so is there any steps we have to perform or something else please guide me what should i do?
#import "Hello_SOAPViewController.h"
#interface NSURLRequest (withHttpsCertificates)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
#end
#implementation Hello_SOAPViewController
NSMutableData *webData;
- (void)viewDidLoad {
//////////////////////////////////////////////////
//Web Service Call
////////////////////////////////////
NSURL *url = [NSURL URLWithString:#"https://192.168.1.105/HelloService/Service.svc/username(user)/password(xxx)"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
[theRequest addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPMethod:#"GET"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
webData = [[NSMutableData data] retain];
}
else {
NSLog(#"theConnection is NULL");
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConnection:%#",[error description]);
if ([error code] == -1001 ){//isEqualToString:#"timed out"]) {
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Connection Error" message:#"Server Unresponsive" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alertView show];
}else{
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Connection Error" message:#"Check your internet connection " delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alertView show];
}
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
///////////////////////
//Process Your Data here:
///////////////////////
[connection release];
[webData release];
}
- (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 {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}

UIActivityIndicatorView when loading image from online?

I have a simple script that displays in a UIImageView from the internet.
Is there a way to display a UIActivityIndicatorView or something of that sort to show the user that it's loading?
Here's my minimal code:
NSString *imagePath = [NSString stringWithFormat:#"urlofimagehere.jpg"];
NSData *mydata = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imagePath]];
UIImage *myimage = [[UIImage alloc] initWithData:mydata];
[imageView setImage:myimage];
[myimage release];
Thanks!
Coulton
EDIT: CODE REMOVED
-[NSData initWithContentsOfURL:]
is a synchronous method. This means it will block until the data is loaded over the network. If you want to be able to keep your UI responsive, you'll want to use an asynchronous approach. For more info, read this: http://akosma.com/2010/05/28/initwithcontentsofurl-methods-considered-harmful/
I'd recommend using NSURLRequest with an NSURLRequestDelegate to receive callbacks when the data is finished loading. Here's an example:
- (void)loadImageAtURL(NSString *)urlString {
[myUIActivityIndicatorView startAnimating];
// SHOW NETWORK INDICATOR
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// SET UP THE REQUEST
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSURLRequest *request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
// SET UP THE CONNECTION
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
mutData = [[[NSMutableData alloc] init] retain];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error {
// Handle error
}
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data {
[mutData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection {
// ONCE LOADED HIDE NETWORK INDICATOR
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
// RELEASE THE CONNECTION
[connection release];
// CREATE NEW UIIMAGE FROM THE DATA
image = [[[UIImage alloc] initWithData:mutData] retain];
[mutData release];
// HIDE THE ACTIVITY INDICATOR
// Make sure hidesWhenStopped is set to YES on the activity indicator.
[myUIActivityIndicatorView stopAnimating];
[myUIImageView setImage:image];
[image release];
}
Hope this helps!