I want to implement Pull To Refresh to my UITableViewController by using UIRefreshControl. Here what i tried so far.
- (void)viewDidLoad
{
.....
////********* Pull to refresh ************/
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to Refresh"];
refresh.tintColor = [UIColor magentaColor];
// [self.tableView addSubview:refresh];
// [self.refreshControl setEnabled:YES];
[refresh addTarget:self action:#selector(pullToRefresh:) forControlEvents:UIControlEventValueChanged];
self.refreshControl = refresh;
}
-(void)pullToRefresh:(UIRefreshControl *)refresh {
[refresh beginRefreshing];
refresh.attributedTitle = [[NSAttributedString alloc] initWithString:#"Refreshing.."];
[self loadRecentActivities];
}
But when i pull the tableview neither activity indicator nor title is visible, however pullToRefresh is called and table refreshed.My app supports iOS7.0+.
What i'm missing? Any help would be appreciated?
Edit: I'v tried with [self.refreshControl setEnabled:YES]; and [self.refreshControl setEnabled:YES]; as mentioned in my edited code, but still no luck.
This is how my tableview looks like when i pull it to refresh-
Final Solution: For table view background i was using
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = imageView;
Refresh indicator and title was hidden behind the self.tableView.backgroundView instead use
[self.tableView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background.png"]]];
and it solves my problem. also many thanks to Balram Tiwari please see his answer if you still have problem.
Just add self.tableView.backgroundView.layer.zPosition -= 1; under the initialisation code for refreshControl.
Actually you have your refresh controller there in the tableView, but it is behind the navigationBar. (Sounds different, right), Here is the catch,
When you are using code in iOS7, by default the UIViewController takes the (edgesForExtendedLayout) whole screen. That means your (0,0) will start from the top left corner, underneath the navigationBar.
So your tableView is actually starting from there. So to get rid of it, you just specify the edgesForExtendedLayout for your viewController in your viewDidLoad Method.
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
After that it should be visible.
Before above Fix:
After the Fix.
hope that helps.
Related
I'm using pull to refresh with UICollectionView that has an header(i don't know if the header is relevant) . When i'm pull to refresh right before the refresh part the collection view jumps down(not smoothly at all).
What could be the problem?
here is my code -
- (void)addRefresh
{
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(reset) forControlEvents:UIControlEventValueChanged];
[self.refreshControl setBackgroundColor:[UIColor whiteColor]];
[self.profileCollectionView addSubview:self.refreshControl];
}
- (void)reset
{
[self.refreshControl endRefreshing];
}
I had a similar but not exactly the same problem with UIRefreshControl where the text would overlap the UIActivityIndicator of the UIRefreshControl. This would only happen the first time you would activate the UIRefreshControl. I'm not sure if this fix will help you but you can give it a try:
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//Fix for bug where spinner would overlap the text
dispatch_async(dispatch_get_main_queue(), ^{
[_refreshControl beginRefreshing];
[_refreshControl endRefreshing];
});
}
I have horizontal UICollectionView with UIRefreshControl:
self.refreshControlMain = [[UIRefreshControl alloc] init];
//self.refreshControlMain.tintColor = [UIColor grayColor];
[self.refreshControlMain addTarget:self action:#selector(refershControlAction) forControlEvents:UIControlEventValueChanged];
[self.collectionViewMain addSubview:self.refreshControlMain];
self.collectionViewMain.alwaysBounceVertical = YES;
self.collectionViewMain.pagingEnabled = YES;
self.collectionViewMain.showsHorizontalScrollIndicator = NO;
self.collectionViewMain.scrollEnabled = NO;
//Because user can't scroll horizontally (he needs to press next button)
But this code doesn't work, because I can't drag it vertically.
The only option I found is to set self.collectionViewMain.scrollEnabled = YES; (and in this case I can drag it vertically, so that refresh control appears), but in this case user is able to scroll horizontally (but user shouldn't be able to do that).
Is there any option to use refresh control in my situation?
update:
I don't need horisontal refresh control. I have horisontal collectionview, but I need vertical refresh control. if I put "self.collectionViewMain.scrollEnabled = YES" in my code, it works. but I need user not be able to scroll himself.
UIRefreshControl does not support horizontal use natively.
There are various solutions whereby it has been extended for horizontal use.
Check out this link.
Or as per this answer you could use a UITableViewController that is rotated 90 degrees.
Add [self.view setTransform:CGAffineTransformMakeRotation(-M_PI / 2)]; in the UITableViewController class during setup.
Example using UITableView (and not UITableViewController):
table_ = [[UITableView alloc] initWithFrame:self.bounds];
[table_ setDelegate:self];
[table_ setDataSource:self];
[table_ registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Cell"];
[table_ setTransform:CGAffineTransformMakeRotation(-M_PI / 2)];
UIRefreshControl *ctrl = [[UIRefreshControl alloc] init];
[ctrl setBackgroundColor:[UIColor yellowColor]];
[table_ addSubview:ctrl];
[self addSubview:table_];
Make sure to remember to rotate the content back again in the opposite direction!
Im try the pull down to refresh in collection view but im use the (tableview pull down to refresh controller)same code for collection view. Please any one help my problem.
Firstly you can write this code in your viewDidLoad :-
- (void) viewDidLoad
{
[super viewDidLoad];
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
refreshControl.tintColor = [UIColor blackColor];
refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to Refresh"];
[refreshControl addTarget:self action:#selector(refreshControlAction) forControlEvents:UIControlEventValueChanged];
[collectionView addSubview:refreshControl];
}
Now add a target
- (void) refreshControlAction
{
// Enter your code for request you are creating here when you pull the collectionView. When the request is completed then the collectionView go to its original position.
}
When initiating a view from a UIActionSheet button, upon returning to the view via the navigationBar back button, the toolbar while still visible does not have any of the buttons that were previously on it. This error has arisen since updating to iOS 6 and occurs while testing it on the simulator and a device running iOS 6 only. If I comment out the code that hides the toolbar on the view pushed by the UIActionSheet the buttons are added when going back.
I'm making my toolbar items programatically in viewWillAppear and showing the UIActionSheet from the toolbar which I'm accessing via self.navigationController.toolbar.
Any idea what is causing this problem? It's only happened since iOS 6 has come around so is there any changes that I need to take into account regarding viewWillAppear?
This is how the view is pushed from the actionSheet:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (actionSheet.tag == 2) {
if (buttonIndex == 0) {
[self dismissAllTips];
self.actionNoteAddView= [[self.storyboard instantiateViewControllerWithIdentifier:#"IDActionNoteAddView"] retain];
actionNoteAddView.note_id = 0;
actionNoteAddView.iscompleted=0;
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"tool_tips"];
[self.navigationController pushViewController:actionNoteAddView animated:TRUE];
[actionNoteAddView release];
}else if(buttonIndex == 1){
...
These are the view methods for the pushed view:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationItem.hidesBackButton = NO;
[self.navigationController setToolbarHidden:YES];
txtcontent.layer.cornerRadius = 10.0f;
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
These are the view methods for the view that pushed the view using the actionSheet:
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.navigationItem.hidesBackButton = YES;
[self.navigationController setToolbarHidden:NO];
self.navigationController.navigationBarHidden=NO;
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
self.navigationController.toolbar.barStyle = UIBarStyleBlackOpaque;
self.navigationController.toolbar.tintColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
UIImage *actionButtonImage = [UIImage imageNamed:#"31-circle-plus#2x.png"];
UIBarButtonItem *actionButton = [[UIBarButtonItem alloc] initWithImage:actionButtonImage style:UIBarButtonItemStylePlain target:self action:#selector(actionPressed:)
];
UIImage *dashButtonImage = [UIImage imageNamed:#"19-gear.png"];
UIBarButtonItem *dashButton = [[UIBarButtonItem alloc] initWithImage:dashButtonImage style:UIBarButtonItemStylePlain target:self action:#selector(settingsPressed:)];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil
action:nil];
NSArray *toolitems = [NSArray arrayWithObjects:dashButton, flexItem, actionButton, flexItem, nil];
[self setToolbarItems:toolitems];
self.title = #"Dashboard";
defaultProfile.text = [[NSUserDefaults standardUserDefaults] stringForKey:#"default_profile"];
BOOL dailyProcess = [[NSUserDefaults standardUserDefaults] boolForKey:#"daily_process"];
if(dailyProcess){
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:#"daily_process"];
[[NSUserDefaults standardUserDefaults] synchronize];
loading = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
labelProcess = [[UILabel alloc]initWithFrame:CGRectMake(60, 105, 240, 30)];
labelProcess.text = #"Processing...";
labelProcess.backgroundColor = [UIColor clearColor];
labelProcess.textColor=[UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
[labelProcess setFont:[UIFont systemFontOfSize:20]];
loading.opaque = NO;
loading.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.6f];
indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[indicator setHidesWhenStopped:YES];
indicator.center = self.view.center;
[self.view addSubview:loading];
[self.view addSubview:indicator];
[self.view addSubview:labelProcess];
[indicator startAnimating];
}
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
CGRect frame = CGRectMake(157, 365, 10, 10);
UIView *viewToPointAt = [[UIView alloc] initWithFrame:frame];
[self.view addSubview:viewToPointAt];
BOOL willies = [[NSUserDefaults standardUserDefaults] boolForKey:#"tool_tips"];
if(willies==YES){
if(popTip == nil) {
popTip = [[[CMPopTipView alloc] initWithMessage:#"Step 1/3: This is the Action Button. You can create, view and auto-fill notes which are then added to your timeline.(Click for step 2)."] autorelease];
popTip.delegate = self;
[popTip presentPointingAtView:viewToPointAt inView:self.view animated:YES];
popTip.backgroundColor = [UIColor colorWithRed:0.8 green:0.45 blue:0.2 alpha:1];
popTip.textColor = [UIColor whiteColor];
}
}
[viewToPointAt release];
}
Tried a lot of different techniques and eventually sorted it by showing it in one view method and hiding it in the next. It's one fo the strangest bugs I have encountered and this is hardly a fix, but I hate having unanswered questions.
You may solve this by hiding the toolbar in the next view, but that is not a very good solution, as other views that can be possibly opened from the view that contains the toolbar will all have to hide the toolbar when needed, this is annoying.
Another solution is to hide the toolbar in viewDidDisappear but there is another problem, let's say another new view needs the toolbar as well, and it sets the toolbar visible in its own viewWillAppear then the problem is that the viewWillAppear for the new view will be called actually before viewDidDisappear of the previous view, so in that case the toolbar disappear even the new view desires it.
Anyway, I'm not sure if this is a bug of iOS6 as it works fine for iOS5, what worked for me was to wrap the code that opens the new view into dispatch_async(dispatch_queue_t queue, dispatch_block_t block), my understanding is that by doing this the action sheet will be dismissed before the new view is shown as you put the code that opens the new view to the end of the main queue(like what we did for viewDidDisappear, but this happens before the call to viewWillAppear of next view so it works perfect).
Got the solution, and I think it is an Apple bug in iOS 6.0 and above.
In the NavigationController view stack if any view hides the toolbar, e.g. self.navigationController.toolbarHidden = YES, then since that point on all the Views that had already created a toolBar with buttons, will loose the buttons.
So, my solution to this problem was to keep the toolBar in all the Views(had to compromise on the UI, but in my app pikSpeak, the functionality was very important.)
This is an ancient thread, I know, but I just recently ran into this problem. The clue to my solution was that some delay was needed between pushing a new view and closing the action sheet. I changed from using clickedButtonAtIndex to didDismissWithButtonIndex so that the push would occur after the action sheet was gone. Problem solved!
What I want to achieve is a UISearchBar that moves up and covers the UINavBar, and contains a cancel button on the right of it. All goes well, until I use the following line of code:
searchDC = [[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self] autorelease];
What ends up happening is the UITableView just won't scroll, but everything else functions as expected. If I remove that line, my nav bar is visible, and the search bar just sits below it, also lacking a cancel button.
Any ideas?
The code for drawing the search bar is:
self.navigationItem.title = #"Search";
searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.bounds.size.width, 44.0f)] autorelease];
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
searchBar.keyboardType = UIKeyboardTypeAlphabet;
searchBar.delegate = self;
[searchBar becomeFirstResponder];
tableView.tableHeaderView = searchBar;
tableView.tableHeaderView.frame = CGRectMake(0.f, 0.f, 480.f, 44.f);
searchDC = [[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self] autorelease];
searchDC.searchResultsDataSource = self;
searchDC.searchResultsDelegate = self;
searchDC.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
searchDC.searchResultsTableView.scrollEnabled = YES;
overlayView.frame = CGRectMake(0, 50, 320, 480);
[self.view addSubview:overlayView];
[self.view bringSubviewToFront:overlayView];
Not enough information to answer this. You need to show the UIViewController or UINavigation Controller code (both the .h and .m) where you are setting up the UISearchDisplayController.
EDIT:
You're implementing this totally wrongly. Apple has a great example on how to implement this http://developer.apple.com/iphone/library/samplecode/TableSearch/Introduction/Intro.html
From Apple's Documentation,
Delegate for the search display controller (delegate), which responds to events such the starting or ending of a search, and the showing or hiding of the search interface.
Set the delegate to your UITableViewController
searchDC.delegate = self;
Also add the searchDC's searchBar to the tableView's headerView
[self.tableView setTableHeaderView:searchDC.searchBar];