I have a method that loads data asynchronously.
-(void)loadingDataAsynchronously{
NSURL *url = [NSURL URLWithString:#"http://vbahrain.azurewebsites.net/api/yearapi"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSData *data = [[NSData alloc] initWithContentsOfURL:location];
NSArray *array = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
self.yearBucket = [NSMutableArray array];
for (NSDictionary * dict in array) {
Year *year = [[Year alloc ]init];
year.yearName =[dict objectForKey:#"Year"];
year.speeches = [dict objectForKey:#"Speeches"];
[self.yearBucket addObject:year];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}];
[task resume];
}
This is the code that I'm using to load the MPProgressHUD.
- (void)viewDidLoad
{
[super viewDidLoad];
HUD = [[MBProgressHUD alloc] initWithView:self.view];
[self.view addSubview:HUD];
HUD.mode = MBProgressHUDModeDeterminate;
HUD.labelText = #"Loading";
HUD.delegate = self;
[HUD showWhileExecuting:#selector(loadingDataAsynchronously) onTarget:self withObject:Nil animated:YES];
}
The MPProgressHUD appears and vanishes in a second. How do I get to show the MPProgressHUD to display the actual progress on loading data in the background thread.
You can try to remove the HUD inside the loadingDataAsynchronously method.
- (void)viewDidLoad
{
[super viewDidLoad];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self loadingDataAsynchronously];
});
}
-(void)loadingDataAsynchronously{
NSURL *url = [NSURL URLWithString:#"http://vbahrain.azurewebsites.net/api/yearapi"];
...
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
...
}
Related
I'm using a UIPageViewController to display items from a JSON file. It works fine except for the first page which displays nothing on loading, but if I come back, it works.
Code is as follows:
#import "SJPagesViewController.h"
#import "SJChildViewController.h"
#interface SJPagesViewController ()
#end
#implementation SJPagesViewController
#synthesize urlToFollow, data,articlesArray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
...
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
CGFloat window_height = ([self window_height]-30.0);
CGFloat window_width = [self window_width];
CGRect pageFrame = CGRectMake(0.0f, 0.0f,window_width , window_height);
self.pageController.dataSource = self;
[[self.pageController view] setFrame:pageFrame];
SJChildViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
//Download JSON
NSError *error=nil;
NSURL *url = [NSURL URLWithString:urlToFollow];
data = [NSData dataWithContentsOfURL: url options:NSDataReadingMappedIfSafe error:&error];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *response = [dictionary objectForKey:#"items"];
articlesArray = [[NSArray alloc] initWithArray:response];
//NSLog(#"articlesArray = %#", articlesArray);
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [(SJChildViewController *)viewController index];
if (index == 0) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [(SJChildViewController *)viewController index];
index++;
if (index == articlesArray.count) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (CGFloat) window_height {
return [UIScreen mainScreen].applicationFrame.size.height;
}
- (CGFloat) window_width {
return [UIScreen mainScreen].applicationFrame.size.width;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (SJChildViewController *)viewControllerAtIndex:(NSUInteger)index {
SJChildViewController *childViewController = [[SJChildViewController alloc] initWithNibName:#"SJChildViewController" bundle:nil];
childViewController.index = index;
childViewController.arrayCount = self.articlesArray.count;
childViewController.model = [[self.articlesArray objectAtIndex:index]objectForKey:#"modelo"];
childViewController.price = [[self.articlesArray objectAtIndex:index]objectForKey:#"precio"];
childViewController.make = [[self.articlesArray objectAtIndex:index]objectForKey:#"marca"];
childViewController.imageUrl = [[self.articlesArray objectAtIndex:index]objectForKey:#"photoUrl"];
return childViewController;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
if (articlesArray.count >5) {
return 5;
}else return [articlesArray count];
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
#end
And ChildViewController to display items:
#implementation SJChildViewController
#synthesize activityIndicator,imageUrl,price,model,make;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
....
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Activity indicator
activityIndicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0);
[self.view addSubview: activityIndicator];
[activityIndicator startAnimating];
}
-(void)viewDidAppear:(BOOL)animated{
self.scrrenNumber.text = [NSString stringWithFormat:#"Artículo %ld de %ld", ((long)self.index+1), (long)self.arrayCount];
self.lblMake.lineBreakMode = NSLineBreakByWordWrapping;
self.lblMake.text = [NSString stringWithFormat:#"%#",make];
//Donload image
//Download image from url
NSURL *url_1= [NSURL URLWithString:imageUrl];
NSURLRequest *request_1 = [NSURLRequest requestWithURL:url_1];
[NSURLConnection sendAsynchronousRequest:request_1
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
UIImage *img = [UIImage imageWithData:data];
[self.articleImage performSelectorOnMainThread:#selector(setImage:) withObject:img waitUntilDone:YES];
}];
//Activity indicator
self.lblPrice.text = [NSString stringWithFormat:#"%#",price];
self.lblModel.lineBreakMode = NSLineBreakByWordWrapping;
self.lblModel.text = [NSString stringWithFormat:#"%#",model];
[activityIndicator stopAnimating];
}
How can I make it work from the first moment?
Luis, I don't have access to xcode right now but it appears your issue is that you are instantiating childViewController while articlesArray is empty.
In viewDidLoad you are downloading your json file and populating articlesArray after you call your helper method viewControllerAtIndex.
Try downloading your json file and populating the array first like you have here.
//Download JSON
NSError *error=nil;
NSURL *url = [NSURL URLWithString:urlToFollow];
data = [NSData dataWithContentsOfURL: url options:NSDataReadingMappedIfSafe error:&error];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *response = [dictionary objectForKey:#"items"];
articlesArray = [[NSArray alloc] initWithArray:response];
Then create your pageViewController and populate it like you did here.
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
CGFloat window_height = ([self window_height]-30.0);
CGFloat window_width = [self window_width];
CGRect pageFrame = CGRectMake(0.0f, 0.0f,window_width , window_height);
self.pageController.dataSource = self;
[[self.pageController view] setFrame:pageFrame];
SJChildViewController *initialViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];
[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];
Im new here and am stumped trying to add a pull to refresh control to update my xml table view. I'm getting the proper pull to refresh animation, but the data is not refreshing. Please help.
- (void)viewDidLoad {
[super viewDidLoad];
feeds = [[NSMutableArray alloc] init];
NSURL *url = [NSURL URLWithString:#"http://www.PLACEHOLDER.rss.xml"];
parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
[parser setDelegate:self];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
UIRefreshControl *refreshControl = [UIRefreshControl new];
[refreshControl addTarget:self action:#selector(refresh:)
forControlEvents:UIControlEventValueChanged];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull
to refresh..."];
self.refreshControl = refreshControl;
}
- (void)refresh:(UIRefreshControl *)sender {
// ...refresh code
NSURL *url = [NSURL URLWithString:#"http://www.PLACEHOLDER.rss.xml"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
[sender endRefreshing];
}
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];
I have developed an app which uses Asyncimageview and iCarousel.But my issues is that when i'm trying to load the images from urls only activity indicator loads in each view of my iCarousel and no images are loaded.Here is my code
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(AsyncImageView *)view
{
if (view == nil
{
AsyncImageView * view = [[[AsyncImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 280)] autorelease];
view.image=[UIImage imageNamed:#"infobg.png"];
view.imageURL=[imageURLs objectAtIndex:index];
}
return view;
}
Follow these steps maybe because of following reasons you may face this issue
-- Check whether if ur imageURLs array is having objects under iCarousel are not...If its null you may have this kind of issue....
-- Do array allocation and add objects in
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
method,because if you add objects in your array under viewDidLoad it won't works because carousel view loads first before viewDidLoad method..
-- if your array element is present even after these steps follow this code.
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(AsyncImageView *)view
{
view = [[[AsyncImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 280)] autorelease];
view.image=[UIImage imageNamed:#"infobg.png"];
view.imageURL=[imageURLs objectAtIndex:index];
//NSLog(#"%#",imageURLs)//check imageURLs having object
if(view ==nil)
{
[[AsyncImageLoader sharedLoader]cancelLoadingImagesForTarget:view];
}
return view;
}
It will help you..
Cells should be reused
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(AsyncImageView *)view
{
if (view == nil) {
view = [[[AsyncImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 280)] autorelease];
}
// dont forget stop previous loading -cancelLoadingURL:target:
view.image=[UIImage imageNamed:#"infobg.png"];
view.imageURL=[imageURLs objectAtIndex:index];
return view;
}
also you should stop previously started
- (void)viewDidLoad
{
[super viewDidLoad];
User_Id=#"abcd#gmail.com";
NSString *Post=[NSString stringWithFormat:#"email=%#",User_Id];
NSData *PostData = [Post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
NSString *PostLengh=[NSString stringWithFormat:#"%d",[Post length]];
NSURL *Url=[NSURL URLWithString:[NSString stringWithFormat:#"%#fetch_all_user_updates.php",ServerPath]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:Url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
[request setValue:PostLengh forHTTPHeaderField:#"Content-Lenght"];
[request setHTTPBody:PostData];
NSData *ReturnData =[NSURLConnection sendSynchronousRequest:request returningResponse:Nil error:Nil];
NSString *Response = [[NSString alloc] initWithData:ReturnData encoding:NSUTF8StringEncoding];
Response = [Response stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSMutableArray *JSON_Array=[Response JSONValue];
// NSlog(#"%#", JSON_Array);
// textfield.text=[[JSON_Array valueforKey:#"email"]objectAtIndex:0];
// load images from database at local host
/*
NSLog(#"%#",[NSString stringWithFormat:#"%#/Images/%#",serverScriptpath,[[jsonarray valueForKey:#"image"]objectAtIndex:0]]);
NSURL *img_url=[NSURL URLWithString:[NSString stringWithFormat:#"%#/Images/%#",
serverScriptpath,[[jsonarray valueForKey:#"image"]objectAtIndex:0]]];
NSURLRequest *request1=[NSURLRequest requestWithURL:img_url];
[Img_profilepic setImageWithURLRequest:request1 placeholderImage:[UIImage imageNamed:#".png"] success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
*/
if (JSON_Array>0)
{
Array_Image_Name=[JSON_Array valueForKey:#"image_name"];
[Array_Image_Name retain];
}
else
{
UIAlertView *Alert=[[UIAlertView alloc]initWithTitle:#"Failure" message:#"Error To Load Image" delegate:Nil cancelButtonTitle:#"OK" otherButtonTitles:Nil, nil];
[Alert show];
[Alert release];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return Array_Image_Name.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
cell=nil;
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
AsyncImageView *Load_Image=[[AsyncImageView alloc]initWithFrame:CGRectMake(20, 10, 280, 100)];
Load_Image.imageURL=[NSURL URLWithString:[NSString stringWithFormat:#"%#/Images/%#",ServerPath,[Array_Image_Name objectAtIndex:indexPath.row]]];
Load_Image.showActivityIndicator=YES;
[cell.contentView addSubview:Load_Image];
return cell;
}
AsyncImageView *asyncImage = [[AsyncImageView alloc] initWithFrame:CGRectMake(0.0f, 1.0f, 320.0f, 174.0f)];
NSString *imgUrlString = photobig1;
while ([imgUrlString rangeOfString:#" "].location != NSNotFound) {
imgUrlString = [imgUrlString stringByReplacingOccurrencesOfString:#" " withString:#""];
}
UIImageView *imageview = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"Loading Image.png"]];
[asyncImage addSubview:imageview];
asyncImage.tag = 999;
NSString *webStr = [NSString stringWithFormat:#"%#",imgUrlString];
NSURL *imageUrl = [[NSURL alloc] initWithString:[webStr stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
[asyncImage loadImageFromURL:imageUrl];
[asyncImage setBackgroundColor:[UIColor clearColor]];
asyncImage.userInteractionEnabled = NO;
[scrollView addSubview:asyncImage];
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!