How to end UIRefreshControl without UITableViewController - iphone

I have created a UIRefreshcontrol without a TableViewController. My question is how I would end it inside another method?
This is how I created it;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(handleRefresh) forControlEvents:UIControlEventValueChanged];
[_tableView addSubview:refreshControl];

I discovered with help from #Justin Paulsson that this could be done;
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[_tableView addSubview:refreshControl];
-
-(void) handleRefresh:(UIRefreshControl *)controller
{
//Refresh code
controller.endRefreshing;
}

The documented way is using an UITableViewController. Anything else can work, but as it's not documented, it may break on next iOS versions.
I'd just use an UITableViewController in your case.

It turns out that UIRefreshControl doesn't require a UITableView at all. refreshControl is a property of UIScrollView. You can set it on anything that inherits from UIScrollView, which includes UITableView of course, but also other classes such as UICollectionView.

Related

UIRefreshControl sticks up at top of table

I'm using UIRefreshControl in UITableviewController. The first time the table loads data coming from internet it automatically shows up at the top. See image below.
This is how I'm setting my refresh control
[self.refreshControl addTarget:self action:#selector(doRefresh:) forControlEvents:UIControlEventValueChanged];
- (void)doRefresh:(CKRefreshControl *)sender {
NSLog(#"Refreshing Parent");
// bring Data Here
}
This all happens before pull-to-refresh. First time when simple table data is populated the refresh control is shown instead of being hidden under the navigation bar.
Can anyone tell me why this is happening?
Try Allocating a new UIRefreshControl object and set the self.refreshControl to it. Something like that:
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl setAttributedTitle:[[NSAttributedString alloc] initWithString:#"Refreshing.."]];
[refreshControl addTarget:self action:#selector(doSomething:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
Hope it helps.
EDIT: Also you should use [self.refreshControl endRefreshing] at the end of the invoked selector.

UIRefreshControl issues

I am trying to implement the UIRefreshControl in my application. I have an xib file and I added a UITableViewController to the empty nib file and I set the refresh property to "enabled". Also I have added code to the viewDidLoad and a custom refresh method. The problem is I have an error I can't find any information on....in my viewDidLoad I get "Property 'refreshControl' not found on object of type ViewController"
- (void)viewDidLoad{
[super viewDidLoad];
self.myTableView =
[[UITableView alloc] initWithFrame:self.view.bounds
style:UITableViewStyleGrouped];
self.myTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
[self.view addSubview:self.myTableView];
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to Refresh"];
[refresh addTarget:self action:#selector(refreshView:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
}
-(void)refreshView:(UIRefreshControl *)refresh {
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Refreshing data..."];
// custom refresh logic would be placed here...
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MMM d, h:mm a"];
NSString *lastUpdated = [NSString stringWithFormat:#"Last updated on %#",
[formatter stringFromDate:[NSDate date]]];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:lastUpdated];
[refresh endRefreshing];
}
I have no idea why that property isn't available....what am I missing?
Looks like I need to inherit from UITableViewController in my ViewController.h file. If I already have UITableView there how do I inherit from both? If I change my code from ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> to ViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> then I get an error:
error: NSInternalInconsistencyException',
reason: '-[UITableViewController loadView] loaded the "ViewController_iPhone" nib but didn't get a UITableView.'
You can add UIRefreshControl as a subview to your UITableView.
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(handleRefresh:) forControlEvents:UIControlEventValueChanged];
[self.myTableView addSubview:refreshControl];
As per Dave's comment, this may break in future version of iOS. So please be careful while using this and try to raise a bug report to apple regarding this.
Update:
A better approach is by adding UITableViewController as a ChildViewController of self and then adding tableViewController.tableView as the subview of self.view. You dont have to do any hack to make it work in this way.
[self addChildViewController:tableViewController];
[self.view addSubview:tableViewController.tableView];
You can define the frame for tableView accordingly. Using this approach, UIRefreshControl should work in the same way as it works for UITableViewController.
`
Things to Remember:
UIRefreshControl only for UITableViewController, so your class should be the subclass of UITableViewController.
UITableViewController has a property refreshControl, you should allocate a UIRefreshControl
and set it to that property.
Ex:
UITableViewController *tableViewController = [[UITableViewController alloc] initWithStyle:UITableViewStylePlain];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self action:#selector(refreshControlAction:) forControlEvents:UIControlEventValueChanged];
tableViewController.refreshControl = refreshControl;
All of these are complex ways of doing something simple.
You don't need to add a refresh control, or declare one in your viewController. Adding pull-to-refresh is a two-step process.
Step 1: In your storyboard, go to your tableViewController and, where it says "Refreshing", select "Enabled".
Step 2: Add the following code to your tableViewController.m file, in viewDidLoad:
[self.refreshControl addTarget:self
action:#selector(refresh)
forControlEvents:UIControlEventValueChanged];
That's the entire process, other than doing stuff in your -refresh method. When you want it to stop refreshing, call [self.refreshControl endRefreshing];.
Your ViewController class must be a subclass of UITableViewController in order to have access to the refreshControl property.
I would recommend you to make separate UITableViewController Subclass for myTableView.
And then by using addChildviewController or iOS6 ContainerView to add that class within original ViewController. That way even in the part of View, you can use UIRefreshControl.
Accepted answer is not official way, so it could break in future release as comment said...

UISearchBar delegate not responding to cancel button

I have a UIViewController that is a UISearchBarDelegate and a MKMapViewDelegate. The searchBarSearchButtonClicked event works fine, but when testing in iOS 4.2 the searchBarCancelButtonClicked never gets called when hitting the cancel button. In 4.3 everything works fine. I have other views with identical code and it works fine. I have triple checked the method signatures.
Could it be something to do with the MapView, or am I doing something blatantly wrong?
My .h file:
#interface MyViewController : UIViewController <UISearchBarDelegate,MKMapViewDelegate,UIAlertViewDelegate>{
MKMapView *mapMainView;
UISearchBar *sBar;
}
#property (nonatomic, retain) UISearchBar *sBar;
#end
And I create the search bar like so:
sBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320.0, 70.0)] autorelease];
sBar.delegate = self;
sBar.showsCancelButton = YES;
[self.view addSubview:sBar];
[sBar becomeFirstResponder];
The method:
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
searchBar.hidden = YES;
}
Does anyone have an idea of why this may be happening?
I had the exact same problem. Holding the cancel button for a few seconds worked.
The reason for me was that I had implemented UITapGestureRecognizer in the tableview. So this took precedence over the button click or 'x' button click in the search bar.
The solution in my case was to restrict the gesture recognition to only the backgroundview of the tableview. I guess similar thing might be happening in your case. Try to restrict the gesture recognizers to the minimum subview required and the search bar should be outside that view.
Probably your sbar object are releasing, in this case is an autorelease object, Why ?. Try declaring sBar as IBOutlet property. Make the apropiate links in the Interface Builder, remove the alloc as you code it, put in viewDidUnload
self.sbar = nil;
and releas it in dealloc. in viewDidLoad put this.
sBar.delegate = self;
sBar.showsCancelButton = YES; // this is an option in object inspector
[self.view addSubview:sBar];
[sBar becomeFirstResponder]; //remove this.
Tell me if it works
try this:
sBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320.0, 70.0)];
sBar.delegate = self;
sBar.showsCancelButton = YES;
[self.view addSubview:sBar];
and try to put release in dealloc
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.searchDisplayController.searchResultsTableView)
{
[self.searchDisplayController setActive:NO animated:YES];
[self.searchDisplayController.searchBar resignFirstResponder];
}
}

How to initialize a button using editButtonItem

I have a table view , within that tableview I'm setting up a section header, which I want to contain an edit button.
I know there is a built in support for something like that if my viewcontroller is part of a navigation chain, but is there a way to do it without it, or the only option is to set a button manually and trigger an action that will replace the title and the editing property?
btw - I know the code I wrote below is wrong, just wondering if there is a convenient way to convert a UIBarButtonItem to a UIButton. Thanks
-(UIView*) headerView
{
if (headerView)
return headerView;
float w = [[UIScreen mainScreen] bounds].size.width;
CGRect headerViewFrame = CGRectMake(0,0, w,48);
headerView = [[UIView alloc] initWithFrame:headerViewFrame];
[headerView addSubview:[self editButtonItem]]; // I want to do something like that
}
There is no way to convert a UIBarButtonItem into a UIButton. If you look at each of their superclasses you will find that UIBarButtonItem inherits from UIBarItem which inherits from NSObject (not related at all to UIButton which from UIView and conforms to the UIResponder protocol).
For this specific problem you can override the following method:
- (void) setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing: editing animated: animated];
[self.tableView setEditing:editing animated:animated];
}
and have a button (you can use it as your section header view) trigger a method that sets the edit status

Design UI programmatically

I'm trying desperately to design my UI programmatically.
But I think I'm in trouble to understand the concept.
Basically I want a UI which contains different UIViews and a UITableView.
But now I'm stuck with the UITableView.
So my "main view" which should contain all these views is called AddListViewController(it inherence from UIViewController).
In the loadView method of this class I'm trying to add a table, but no chance. Has anyone a good example for me. I'm really dont see the point for a separate UITableView and UITableViewController.
You can create a new UITableView, very simply like this:
UITableView * tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain];
[tableView setDataSource:self];
[tableView setDelegate:self];
[self.view addSubview:tableView];
[tableView release];
EDIT: The above answer beat me to it.
Just create your UITableView and add it as subview:
UITableView *table =
[[UITableView alloc] initWithFrame:CGRectMake(x, y, width, height)
style:UITableViewStyleGrouped];
...
[self.view addSubview: table];
[table release];
In loadView, you have to make every view - including the overall view associated with the view controller.
You perhaps want to do what you are trying to do in viewDidLoad instead?
i many be late in answering but still i am answering it
use:
shareListView.delegate = self;
shareListView.dataSource = self;