MBProgressHUD with Table View how to hide HUD? - ios

well I have my RSS application running perfect, and now i'm trying to add some indicator with MBProgressHUD.
I implement this code in the View Controller under ViewDidLoad
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.labelText = #"Loading";
[HUD show:YES];
so far so good. the indicator is working but of course never disappearing.
I am a newbie, I tried to add to my [HUD hide:yes] in certain parts of the implementation file but it's not working .
how can I hide the indicator when the data finish to load ?
here is my implementation file.
#implementation ListadoArticulosViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// HUD setting
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
HUD.labelText = #"Loading";
[HUD show:YES];
NSURL *feedURL = [NSURL URLWithString:#"http://girlsonlyapp.wordpress.com/feed/"];
feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL];
feedParser.delegate = self;
feedParser.feedParseType = ParseTypeFull;
feedParser.connectionType = ConnectionTypeAsynchronously;
listadoArticulos = [[NSMutableArray alloc] init];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(cargaArticulos) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self cargaArticulos];
}
- (void)cargaArticulos {
[feedParser parse];
}
#pragma mark MWFeedParserDelegate
- (void)feedParserDidStart:(MWFeedParser *)parser {
NSLog(#"Comienza el parseo");
// We emptied the list of items to avoid accumulating
// in subsequent calls
[listadoArticulos removeAllObjects];
// We put up the refresh Control
[self.refreshControl beginRefreshing];
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedInfo:(MWFeedInfo *)info {
// Once we have recovered the items we
// The name of the blog as the view controller title
self.title = #"titles";
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item {
// Add the item to the array downloaded
[listadoArticulos addObject:item];
}
- (void)feedParserDidFinish:(MWFeedParser *)parser {
// Como ya ha finalizado el parse, denemos el parser
[feedParser stopParsing];
// Detenemos el refresh control
[self.refreshControl endRefreshing];
// Refrescamos el table view
[self.tableView reloadData];
// trying to do something
}
- (void)feedParser:(MWFeedParser *)parser didFailWithError:(NSError *)error {
NSLog(#"Ha ocurrido un error al tratar de recuperar los artículos.");
// En caso de que este funcionando el refresh control y
// se produzca un error, lo detenemos.
if ([self.refreshControl isRefreshing]) {
// Detenemos el refresh control
[self.refreshControl endRefreshing];
}
}
#pragma mark UITableViewDelegate / UITableViewDataSource
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ArticuloCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ArticuloCell"];
MWFeedItem *item = [listadoArticulos objectAtIndex:indexPath.row];
cell.titulo.text = item.title;
// Guy Cohen - this is the second label that we can customize , orignally it was link, but it changed
// it to summary
cell.descripcion.text = item.summary;
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return listadoArticulos.count;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ArticuloCell *celda = (ArticuloCell *)sender;
MWFeedItem *item = [listadoArticulos objectAtIndex:[self.tableView indexPathForCell:celda].row];
DetalleViewController *detalleVC = (DetalleViewController *)segue.destinationViewController;
[detalleVC setItem:item];
}
#end

May I recommend using SVProgressHUD instead?
https://github.com/samvermette/SVProgressHUD
You just have to call [SVProgressHUD show] and [SVProgressHUD dismiss]

to show:
[[MBProgressHUD showHUDAddedTo:self.navigationController.view animated:YES] setLabelText:#"Loading"];
to hide:
[MBProgressHUD hideAllHUDsForView:self.navigationController.view animated:YES];

Related

How to dismiss UISearchBar once segued

Creating a search view, this is the code that i did for the main search view.
What happens is if i dont search/filter, the uisearchbar gets dismissed when segueing. but if i search/filter then the uisearchbar stays on the nav bar when seguing.
- (void)viewDidLoad {
[super viewDidLoad];
// There's no transition in our storyboard to our search results tableview or navigation controller
// so we'll have to grab it using the instantiateViewControllerWithIdentifier: method
UINavigationController *searchResultsController = [[self storyboard] instantiateViewControllerWithIdentifier:#"CompanySearchResultsNavigationController"];
// Our instance of UISearchController will use searchResults
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
// The searchcontroller's searchResultsUpdater property will contain our tableView.
self.searchController.searchResultsUpdater = self;
self.searchController.hidesNavigationBarDuringPresentation = NO;
// The searchBar contained in XCode's storyboard is a leftover from UISearchDisplayController.
// Don't use this. Instead, we'll create the searchBar programatically.
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.navigationItem.titleView = self.searchController.searchBar;
self.definesPresentationContext = YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
CompanySearchTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"searchCell" forIndexPath:indexPath];
cell.productImageView.file = (PFFile *)object[#"profileImage"];
cell.productImageView.layer.cornerRadius = cell.productImageView.frame.size.width / 2;
cell.productImageView.clipsToBounds = YES;
[cell.productImageView loadInBackground];
cell.companyNameLabel.text = object[#"username"];
return cell;
}
#pragma mark - UISearchControllerDelegate & UISearchResultsDelegate
// Called when the search bar becomes first responder
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
// Set searchString equal to what's typed into the searchbar
NSString *searchString = self.searchController.searchBar.text;
[self updateFilteredContentForAirlineName:searchString];
// If searchResultsController
if (self.searchController.searchResultsController) {
UINavigationController *navController = (UINavigationController *)self.searchController.searchResultsController;
// Present SearchResultsTableViewController as the topViewController
CompanySearchResultsTableViewController *vc = (CompanySearchResultsTableViewController *)navController.topViewController;
// Update searchResults
vc.searchResults = self.searchResults;
// And reload the tableView with the new data
[vc.tableView reloadData];
}
}
// Update self.searchResults based on searchString, which is the argument in passed to this method
- (void)updateFilteredContentForAirlineName:(NSString *)companyName
{
if (companyName == nil) {
// If empty the search results are the same as the original data
self.searchResults = [self.objects mutableCopy];
} else {
NSMutableArray *searchResults = [[NSMutableArray alloc] init];
// Else if the airline's name is
for (PFObject *company in self.objects) {
if ([company[#"username"] containsString:companyName]) {
// NSString *str = [NSString stringWithFormat:#"%#", company[#"username"]];
// [searchResults addObject:str];
PFObject *searchedObject = company;
[searchResults addObject:searchedObject];
NSLog(#"Searched: %#",searchedObject[#"username"]);
}
self.searchResults = searchResults;
}
}
}
In your AirlineTableViewController, override [UIViewController prepareForSegue]:
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender {
[self.searchController setActive:NO];
}

Search result auto complete does not display iOS Objective C

I've tried reading the google places API. and tried to duplicate their work. But I think I'm missing some steps here.
Here is the code for header my header file.
#class SPGooglePlacesAutocompleteQuery;
#interface GoogleMapViewViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate, MKMapViewDelegate, UISearchControllerDelegate>
{
NSArray *searchResultPlaces;
SPGooglePlacesAutocompleteQuery *searchQuery;
MKPointAnnotation *selectedPlaceAnnotation;
BOOL shouldBeginEditing;
}
#property (strong, nonatomic) UISearchController *searchController;
#property (retain, nonatomic) IBOutlet MKMapView *mapView;
#end
My implementation file
#import "GoogleMapViewViewController.h"
#import "SPGooglePlacesAutocompleteQuery.h"
#import "SPGooglePlacesAutocompletePlace.h"
#interface GoogleMapViewViewController ()
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#end
#implementation GoogleMapViewViewController
#synthesize mapView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
searchQuery = [[SPGooglePlacesAutocompleteQuery alloc] init];
searchQuery.radius = 100.0;
shouldBeginEditing = YES;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.searchBar.placeholder = #"Search or Address";
self.searchBar.delegate = self;
}
- (void)viewDidUnload {
[self setMapView:nil];
[super viewDidUnload];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [searchResultPlaces count];
}
- (SPGooglePlacesAutocompletePlace *)placeAtIndexPath:(NSIndexPath *)indexPath {
return [searchResultPlaces objectAtIndex:indexPath.row];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"SPGooglePlacesAutocompleteCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.textLabel.font = [UIFont fontWithName:#"GillSans" size:16.0];
cell.textLabel.text = [self placeAtIndexPath:indexPath].name;
return cell;
}
#pragma mark UITableViewDelegate
- (void)recenterMapToPlacemark:(CLPlacemark *)placemark {
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta = 0.02;
span.longitudeDelta = 0.02;
region.span = span;
region.center = placemark.location.coordinate;
[self.mapView setRegion:region];
}
- (void)addPlacemarkAnnotationToMap:(CLPlacemark *)placemark addressString:(NSString *)address {
[self.mapView removeAnnotation:selectedPlaceAnnotation];
selectedPlaceAnnotation = [[MKPointAnnotation alloc] init];
selectedPlaceAnnotation.coordinate = placemark.location.coordinate;
selectedPlaceAnnotation.title = address;
[self.mapView addAnnotation:selectedPlaceAnnotation];
}
- (void)dismissSearchControllerWhileStayingActive {
// Animate out the table view.
NSTimeInterval animationDuration = 0.3;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
self.searchDisplayController.searchResultsTableView.alpha = 0.0;
[UIView commitAnimations];
[self.searchDisplayController.searchBar setShowsCancelButton:NO animated:YES];
[self.searchDisplayController.searchBar resignFirstResponder];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SPGooglePlacesAutocompletePlace *place = [self placeAtIndexPath:indexPath];
[place resolveToPlacemark:^(CLPlacemark *placemark, NSString *addressString, NSError *error) {
if (error) {
SPPresentAlertViewWithErrorAndTitle(error, #"Could not map selected Place");
} else if (placemark) {
[self addPlacemarkAnnotationToMap:placemark addressString:addressString];
[self recenterMapToPlacemark:placemark];
[self dismissSearchControllerWhileStayingActive];
[self.searchDisplayController.searchResultsTableView deselectRowAtIndexPath:indexPath animated:NO];
}
}];
}
#pragma mark UISearchDisplayDelegate
- (void)handleSearchForSearchString:(NSString *)searchString {
searchQuery.location = self.mapView.userLocation.coordinate;
searchQuery.input = searchString;
[searchQuery fetchPlaces:^(NSArray *places, NSError *error) {
if (error) {
SPPresentAlertViewWithErrorAndTitle(error, #"Could not fetch Places");
} else {
searchResultPlaces = places;
[self.searchDisplayController.searchResultsTableView reloadData];
}
}];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self handleSearchForSearchString:searchString];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchController:(UISearchController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self handleSearchForSearchString:searchString];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
#pragma mark UISearchBar Delegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (![searchBar isFirstResponder]) {
// User tapped the 'clear' button.
shouldBeginEditing = NO;
[self.searchDisplayController setActive:NO];
[self.mapView removeAnnotation:selectedPlaceAnnotation];
}
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
if (shouldBeginEditing) {
// Animate in the table view.
NSTimeInterval animationDuration = 0.3;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
self.searchDisplayController.searchResultsTableView.alpha = 1.0;
[UIView commitAnimations];
[self.searchDisplayController.searchBar setShowsCancelButton:YES animated:YES];
}
BOOL boolToReturn = shouldBeginEditing;
shouldBeginEditing = YES;
return boolToReturn;
}
#pragma mark MKMapView Delegate
- (MKAnnotationView *)mapView:(MKMapView *)mapViewIn viewForAnnotation:(id <MKAnnotation>)annotation {
if (mapViewIn != self.mapView || [annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString *annotationIdentifier = #"SPGooglePlacesAutocompleteAnnotation";
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:annotationIdentifier];
if (!annotationView) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:annotationIdentifier];
}
annotationView.animatesDrop = YES;
annotationView.canShowCallout = YES;
UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[detailButton addTarget:self action:#selector(annotationDetailButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = detailButton;
return annotationView;
}
- (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views {
// Whenever we've dropped a pin on the map, immediately select it to present its callout bubble.
[self.mapView selectAnnotation:selectedPlaceAnnotation animated:YES];
}
- (void)annotationDetailButtonPressed:(id)sender {
// Detail view controller application logic here.
}
#end
I am really confused now to my implementation file as I cannot really understand what is in there TBH.plus some codes here are mostly deprecated. Someone care to give a detailed guide about this? or explain to me in layman's term. TIA.
ANSWERED!
Basically my problem was in this function given on the sample project of google places API..
BOOL SPEnsureGoogleAPIKey() {
BOOL userHasProvidedAPIKey = YES;
if (![kGoogleAPIKey isEqualToString:#"AIzaSyA2vs9pJoLrLs6XU8IRVHo7WxiuMufYXl8"]) {
userHasProvidedAPIKey = NO;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"API Key Needed" message:#"Please replace kGoogleAPIKey with your Google API key." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
return userHasProvidedAPIKey;
}
The if statement originally is incorrect that's why it always gives me the wrong value. now its working :) just added the not "!" in if

List not being populated from other view

I have a view controller where the user can populate an item. Upon exiting the view that object should be saved, and loaded by the previous view which contains a list of all these objects. My NSLog shows that the object is being saved, but I can't get it to appear in the list view.
Code for both controllers is below. Thanks
List Controller
#import "ItemsViewController.h"
#import "Calculation.h"
#import "CalculationItemStore.h"
#import "CalculationDetailViewController.h"
#interface ItemsViewController()
#property UISegmentedControl *segment;
#end
#implementation ItemsViewController
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
UINavigationItem *navItem = self.navigationItem;
navItem.title = #"MACS";
// Create a new bar button item that will send
// addNewItem: to CalculationsViewController
UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(addNewItem:)];
// Set this bar button item as the right item in the navigationItem
navItem.rightBarButtonItem = bbi;
navItem.leftBarButtonItem = self.editButtonItem;
}
return self;
}
- (instancetype)initWithStyle:(UITableViewStyle)style
{
return [self init];
}
- (void)viewDidLoad
{
self.segment = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Publication", #"About", nil]];
self.tableView.tableHeaderView = _segment;
[_segment addTarget:self action:#selector(segmentPressed:) forControlEvents:UIControlEventValueChanged];
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:#"UITableViewCell"];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[CalculationItemStore sharedStore] allCalculations] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Get a new or recycled cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell" forIndexPath:indexPath];
// Set the text on the cell with the description of the item
// that is at the nth index of items, where n = row this cell
// will appear in on the tableview
NSArray *items = [[CalculationItemStore sharedStore] allCalculations];
Calculation *item = items[indexPath.row];
cell.textLabel.text = item.title;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CalculationDetailViewController *detailViewController = [[CalculationDetailViewController alloc] init];
NSArray *items = [[CalculationItemStore sharedStore] allCalculations];
Calculation *selectedItem = items[indexPath.row];
// Give detail view controller a pointer to the item object in row
detailViewController.calculation = selectedItem;
// Push it onto the top of the navigation controller's stack
[self.navigationController pushViewController:detailViewController
animated:YES];
}
- (void) tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// If the table view is asking to commit a delete command...
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSArray *items = [[CalculationItemStore sharedStore] allCalculations];
Calculation *item = items[indexPath.row];
[[CalculationItemStore sharedStore] removeItem:item];
// Also remove that row from the table view with an animation
[tableView deleteRowsAtIndexPaths:#[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
- (void) tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)destinationIndexPath
{
[[CalculationItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row
toIndex:destinationIndexPath.row];
}
- (void)segmentPressed:(id)sender {
if (_segment.selectedSegmentIndex ==0) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"http://ferm.forestry.oregonstate.edu/facstaff/leshchinsky-ben"]];
}else if(_segment.selectedSegmentIndex ==1){
UIImageView *imageView = [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, 320, 480)];
imageView.backgroundColor = [UIColor redColor];
[imageView setImage: [UIImage imageNamed:#"MACSLoad#2x.png"]];
[self.view addSubview: imageView];
sleep(5);
imageView.hidden = YES;
}
}
- (IBAction)addNewItem:(id)sender
{
// Create a new Calculation and add it to the store
Calculation *newItem = [[CalculationItemStore sharedStore] createCalculation];
CalculationDetailViewController *detailViewController = [[CalculationDetailViewController alloc]initForNewItem:YES];
detailViewController.calculation = newItem;
detailViewController.dismissBlock = ^{
[self.tableView reloadData];
};
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:detailViewController];
navController.modalPresentationStyle = UIModalPresentationFullScreen;
// [self presentViewController:navController animated:YES completion:NULL];
[self.navigationController pushViewController:detailViewController animated:YES];
}
#end
Item controller save method
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
//clear responder
[self.view endEditing:YES];
//save changes
BOOL success = [[CalculationItemStore sharedStore]saveChanges];
if(success){
NSLog(#"Saved all calcs");
}else{
NSLog(#"failure saving");
}
}
I think the issue is that by the time the table reloadData is called on the first controller, the second one is not done loading. You could notify the first VC to reload the data once the second one is done saving It can be notified using
create a delegate on the second one or
using notifications
Let me know if you need more details on how to do this!
Looks like there is also an issue with the object creation.
your calculation elements are not getting created properly. When you are ready to save.. look at the contents of self.privateItems. They values filled in are nil. You will need to instantiate the Strings properly.
engineerName needs to be alloc'd and other strings as well.
and when user hits Done, the values from the text boxes need to be set to the your data model.

UIRefreshControl on viewDidLoad

I'm using the following code to create a UIRefreshControl:
- (void) viewDidLoad
{
[super viewDidLoad];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(doLoad) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
}
- (void) doLoad
{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// Instead of sleeping, I do a webrequest here.
[NSThread sleepForTimeInterval: 5];
dispatch_async(dispatch_get_main_queue(), ^{
[tableView reloadData];
[self.refreshControl endRefreshing];
});
});
}
It works great. If I navigate to my view, drag the table, the code runs and the data displays.
However, what I would like to do is have the view in the 'loading' state as soon as it appears (that way the user knows something is going on). I have tried adding the following:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.refreshControl beginRefreshing];
}
But it does not seem to work. When I navigate to the view, it looks like a regular view (refresh control is not visible), plus when I try to pull the refresh control, it never finished loading.
Obviously I'm going about this the wrong way. Any suggestions on how I should handle this?
Try this:
- (void) viewWillAppear: (BOOL) animated
{
[super viewWillAppear: animated];
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
[self.refreshControl beginRefreshing];
// kick off your async refresh!
[self doLoad];
}
Remember to call endRefreshing at some point!
EDIT to add full working sample:
This sample view controller, built and run in iOS6.1 as the root viewcontroller starts with the UIRefreshControl already visible and animating when the app launches.
TSTableViewController.h
#interface TSTableViewController : UITableViewController
#end
TSTableViewController.m
#import "TSTableViewController.h"
#implementation TSTableViewController
{
NSMutableArray* _dataItems;
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.refreshControl = [UIRefreshControl new];
[self.refreshControl addTarget: self
action: #selector( onRefresh: )
forControlEvents: UIControlEventValueChanged];
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
[self.refreshControl beginRefreshing];
[self onRefresh: nil];
}
- (void) onRefresh: (id) sender
{
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
_dataItems = [NSMutableArray new];
for ( int i = 0 ; i < arc4random() % 100 ; i++ )
{
CFUUIDRef uuid = CFUUIDCreate( NULL );
[_dataItems addObject: CFBridgingRelease(CFUUIDCreateString( NULL, uuid)) ];
CFRelease( uuid );
}
[self.refreshControl endRefreshing];
[self.tableView reloadData];
});
}
#pragma mark - Table view data source
- (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection: (NSInteger) section
{
return _dataItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: nil];
cell.textLabel.text = [_dataItems objectAtIndex: indexPath.row];
return cell;
}
#end
Manually modifying the contentOffset is insecure and wrong and can lead to unexpected behavior in some cases. This solution works without touching the contentOffset at all:
func showRefreshControl(show: Bool) {
if show {
refreshControl?.beginRefreshing()
tableView.scrollRectToVisible(CGRectMake(0, 0, 1, 1), animated: true)
} else {
refreshControl?.endRefreshing()
}
}
Another option is fire a UIControlEventValueChanged in your viewDidAppear: to trigger an initial refresh.
- (void) viewDidAppear: (BOOL) animated
{
[super viewDidAppear: animated];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(doLoad) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
[self.refreshControl beginRefreshing];
}
You never set self.refreshControl

Make buttons populate a UITableView when pressed

I have created a simple rss reader that populates the tableviewcell on viewdidLoad without a problem. My problem is whenever I click my button the tableview doesn't change. I tried reload with the button touchup inside and nothing still happens. Fairly new to Xcode and iOS programming so any help is great.
.m file
#import "ViewController.h"
#import "KMXMLParser.h"
#import "WebViewController.h"
#import "SportsViewController.h"
#interface ViewController ()
#end
#implementation ViewController
{
NSArray *loadData;
NSURL *thumbnails;
}
#synthesize parseResults=_parseResults;
- (void)viewDidLoad
{
[super viewDidLoad];
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://www.daytonastate.edu/rss/it.xml" delegate:nil];
_parseResults = [parser posts];
[self refreshFeed];
// Do any additional setup after loading the view, typically from a nib.
}
-(void) refreshInvoked:(id)sender forState:(UIControlState)state
{
[self refreshFeed];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)refreshFeed
{
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://www.daytonastate.edu/rss/it.xml" delegate:nil];
_parseResults = [parser posts];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return self.parseResults.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"DataCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}// Configure the cell...
cell.textLabel.text = (self.parseResults)[indexPath.row][#"title"];
cell.detailTextLabel.text = (self.parseResults)[indexPath.row][#"summary"];
[self reloadData];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WebViewController *vc = [[WebViewController alloc] init];
vc.url = [NSURL URLWithString:(self.parseResults)[indexPath.row][#"link"] ];
[self.navigationController pushViewController:vc animated:YES];
//Makes sure function clicks to reader feed.
// Navigation logic may go here. Create and push another view controller.
}
-(IBAction)pressBtn:(id)sender
{
UIButton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect];
if (button.tag==1)
{
NSLog(#"Press button 1");
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://www.daytonastate.edu/rss/cea.xml" delegate:nil];
_parseResults = [parser posts];
[self reloadData];
}
if (button.tag==2)
{
NSLog(#"Press button 2");
[self EventsBtn:nil];
}
}
- (IBAction)NewsBtn:(id)sender
{
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://rss.cnn.com/rss/cnn_topstories.rss" delegate:nil];
_parseResults = [parser posts];
NSLog(#"reload happened");
// self.printMessage = [[PrintHello alloc] init]; // EDIT: THIS LINE WAS MISSING NOW IT WORKS
//[self.printMessage Print];
NSLog(#"NewsBtn Pressed");
}
- (IBAction)SportsBtn:(id)sender
{
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://www.daytonastate.edu/rss/it.xml" delegate:nil];
_parseResults = [parser posts];
}
- (IBAction)EventsBtn:(id)sender
{
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://www.daytonastate.edu/rss/events.xml" delegate:nil];
_parseResults = [parser posts];
NSLog(#"eventsBtn Pressed");
}
- (IBAction)WeatherBtn:(id)sender
{
KMXMLParser *parser = [[KMXMLParser alloc] initWithURL:#"http://w1.weather.gov/xml/current_obs/KDAB.rss" delegate:nil];
_parseResults = [parser posts];
}
#end
In your pressBtn: method, replace this line:
UIButton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect];
with:
UIButton *button = (UIButton *)sender;
This assumes that in IB you have already hooked up the pressBtn: method to the appropriate button. The code you had was creating a new button when your pressBtn: action was called. Since this new button has a tag value of 0, nothing happened. The code I propose actually makes use of the button that was tapped by the user.
Using the invoker (sender), that is the item which you had action on it. Dont create a new button, you want to check the tag of button so the new button is not the item for your work.
Try your best man, :).

Resources