How can I defined and check the alreadySelectedSpecificTab and viewControllerNotToAllow in
my application. anyone give me one example for that.
Actuly I would like to do something. like. When second tab is selected that time if we select second tab is not selected only remaing tab is to be selected.
thats why I used the following code.
please reply
- (BOOL)tabBarController:(UITabBarController *)tabBarControllers shouldSelectViewController:(UIViewController *)viewController
{
if(alreadySelectedSpecificTab)
{
if([viewController isEqual:viewControllerNotToAllow])
return NO;
}
return YES;
}
Create some properties in your class
and keep track of what you want denied and what you dont want denied.
id currentlySelected; //This will hold the address of the selected view
id dontAllowSelection; //This will hold the address of the Denied view
- (BOOL)tabBarController:(UITabBarController *)tabBarControllers shouldSelectViewController:(UIViewController *)viewController
{
if (dontAllowSelection != nil && //If it is nil, we will skip it.
dontAllowSelection == viewController) //If the selected view is Denied return NO
{
return NO;
}
currentlySelected = viewController;
if (currentlySelected == someViewIWantToDisableOtherFor) //Any logic can go here to enable the Denied View.
{
dontAllowSelection = anotherViewIWantDisabled; //Set my denied view.
}
else
{
dontAllowSelection = nil; //Unsed the Denial.
}
return YES;
}
Related
Thanks for reading my question.
I'm trying to implement a popup menu when a user clicks the tab with the index of 4. So I'm trying to prevent the tabbar from switching viewcontroller when index 4 is pressed.
Here is my code:
- (BOOL) tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
if(viewController == [tabBarController.viewControllers objectAtIndex:4]){
NSLog(#"NO");
return NO;
}else{
NSLog(#"YES");
return YES;
}
}
I've implemented the UITabBarControllerDelegate and self.delegate = self; in the viewDidLoad and it works but just one time.
When I click the index 4 tab the menu shows and the tabbar doesn't switch view (GREAT), but when I click it again the view changes even if I get the Log "NO".
What could be the problem here?
Thanks you for any suggestions!
SOLVED
Thanks to Kasaname's answer below I solved it by adding selectedindex and set it to a flag index (prevtab). I change the prevtab to the index of the last selected tab, exept for when the user selects index 4.
My final code:
- (BOOL) tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
if(viewController == [tabBarController.viewControllers objectAtIndex:4]){
self.selectedIndex = prevTab; //only change in this method
return NO;
}else{
return YES;
}
}
This is how you can stop/prevent Tabbar items to switch your tab on tabbar item click
For Swift 3.0
Make sure you have implemented UITabBarControllerDelegate and set UITabbarController's delegate to self
then override this delegate in your controller
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if viewController == tabBarController.viewControllers?[2] {
return false
} else {
return true
}
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
if (tabBarController.selectedIndex == 0) {
} else if (tabBarController.selectedIndex == 1) {
} else if (tabBarController.selectedIndex == 2) {
}
}
why dont u use this delegate
Use this delegate it will work i suppose
In iOS6 in the methods viewControllerAfterViewController and viewControllerBeforeViewController if I return nil (for block the page navigation when I am in the first or last page) the app crash with this exception:
'The number of view controllers provided (0) doesn't match the number required (1) for the requested transition'
In iOS5 all works good.
I had the same issue. I found that the cause was replacing the delegate on the UIPanGestureRecognizer of the UIPageViewController, a no-no really. The pan gesture recognizer was calling an undocumented method _gestureRecognizerShouldBegin: (note the leading underscore) that UIPageViewController implements and apparently relies upon to work properly (read: not-crash). I ended up implementing respondsToSelector: and forwardingTargetForSelector: in my class that uses the UIPageViewController to pass the undocumented delegate method on to the UIPageViewController without specifically naming it (and almost certainly earning me an app store review rejection).
-(BOOL)respondsToSelector:(SEL)aSelector {
if ([super respondsToSelector:aSelector])
return YES;
else if ([self.pageViewController respondsToSelector:aSelector])
return YES;
else
return NO;
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([super respondsToSelector:aSelector]) {
return nil;
} else if ([self.pageViewController respondsToSelector:aSelector]) {
return self.pageViewController;
}
return nil;
}
My longer term solution will be to rework the use of UIPageViewController such that I don't need to displace the gesture recognizer delegates.
Ah,was wondering why no one has pointed out this bug,which i took almost 2 nights to find out the solution.
OLD CODE(iOS 5.1) : when returning nil on the first and last page you will experience the app crash.It works fine in iOS 5.1,but in iOS 6 it wont.
- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerBeforeViewController:
(UIViewController *)viewController
{
for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) {
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
recognizer.enabled = NO;
}
}
NSUInteger index = [self indexOfViewController:
(MainViewController *)viewController];
if ((index == 0) || (index == NSNotFound)) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
for (UIGestureRecognizer *recognizer in pageController.gestureRecognizers) {
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
recognizer.enabled = NO;
}
}
NSUInteger index = [self indexOfViewController:
(MainViewController *)viewController];
if (index == NSNotFound) {
return nil;
}
}
SOLUTION(iOS 6) : After adding the gesture effect to the superview,just call the delegate called -(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer. What i did is quiet simple, computing the speed of the user flipping the first page and last page (i mean using the gesture recognizer) , i denied the swiping.All you need to do is just paste the following code,and you are DONE!.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (pageNum==0) {
if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
[(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x > 0.0f) {
//NSLog(#"Swiping to left on 1st page is denied");
return NO;
}
if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
[(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x < self.view.frame.size.width/2) {
//NSLog(#"tapping to left on 1st page is denied");
return NO;
}
}
else if(pageNum ==totalNoOfFiles-1)
{
if ([(UIPanGestureRecognizer*)gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] &&
[(UIPanGestureRecognizer*)gestureRecognizer velocityInView:gestureRecognizer.view].x < 0.0f) {
//NSLog(#"Swiping to right on 1st page is denied");
return NO;
}
if ([(UITapGestureRecognizer*)gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] &&
[(UITapGestureRecognizer*)gestureRecognizer locationInView:gestureRecognizer.view].x > self.view.frame.size.width/2) {
//NSLog(#"Tapping to right on 1st page is denied");
return NO;
}
}
return YES;
}
- (UIViewController *)pageViewController:(UIPageViewController*) pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
int index = [self indexOfViewController:(ChildViewController *)viewController];
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:
(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
int index = [self indexOfViewController:(ChildViewController *)viewController];
index++;
return [self viewControllerAtIndex:index];
}
This has been well discussed but I have one thing to add. Consider why you were setting the delegate of the gesture recognizers to self. In my case, it was because in some cases I wanted to prevent the gesture recognizers from recognizing, with the delegate's gestureRecognizerShouldBegin:.
But in iOS 6, where this issue arises, there is a whole new way of doing exactly that, by implementing gestureRecognizerShouldBegin: on a UIView. (This is a new UIView instance method in iOS 6.)
Thus I was able to accomplish exactly what I was accomplishing before, without altering the gesture recognizers' delegate.
I had the issue with UIPageViewController crashing with iOS6 with the same error ('The number of view controllers provided (0) doesn't match the number required (1) for the requested transition').
None of the above solutions worked for me but I eventually found that moving the following line from viewDidLoad to viewDidAppear fixed it.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
Totally same issue here.
What I did was a hotfix which just to returns clone of before/afterViewController instead of nil, i.e.
// viewController = before/afterViewController
NSUInteger index = [self indexOfViewController:viewController];
// NOTE: return nil crashes in iOS6
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
This means you can page-curl forever but I had no other choice...
Better solution is always welcome.
So I want to present to the user an alert view for them to enter the password. I'd like to check to make sure that something was entered at the keyboard. I know in the UIAlertViewDelegate, you can get the text input. However, the only solution I have so far is,
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"buttonIndex: %i", buttonIndex);
if (buttonIndex == 0) {
UITextField *passwordTextField = [alertView textFieldAtIndex:0];
if (!passwordTextField.text.length == 0) {
NSLog(#"password: %#", passwordTextField.text);
// save the password
}
else {
// Show the alert view again asking for the password
}
}
}
where I would ask for the password again right after they click ok if they didn't enter anything. Is there a better solution to this? Thanks!
Present the alert view again. You can put the alert view in a method and call it.
...
} else {
[self showPassAlert];
}
You can also watch for when the text field is edited, and enable/disable the button in the alert view. If the text field's length is 0, disable the button. When the text field is edited and its length is greater than 0, enable the button. This is more graceful than closing and reopening the view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(textDidChange) name:UITextFieldTextDidChangeNotification object:textField];
...
-(void)textDidChange {
for (UIView *view in alertView.subviews) {
if ([view isKindOfClass:[UIButton class]]) {
if (textField.text.length == 0) {
//you may need to look for the button's title to make sure you are not disabling the cancel button
((UIButton *) view).enabled = NO;
} else {
((UIButton *) view).enabled = YES;
}
}
}
}
Why don't you create iboutlet/reference for your UITextFields, which will aid you to retrieve its value at any moment of time.
i got a 3 view controller - Register, Login, Profile
and i got a UISegmentedControl that i can switch views by from Register to main and from Login to main too.
but when i'm in Register view for Example id like to switch users to profile view after finishing registration.
and here's the Code..
-(IBAction) switchView :(id)sender{
switch (segControl.selectedSegmentIndex) {
case 0:
{
HangmanViewController * main =[[HangmanViewController alloc]initWithNibName:nil bundle:nil];
main.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:main animated:YES];
[main release];
}
break;
case 1:
break;
case 2:
{
Profile *profile2 = [[Profile alloc]initWithNibName:nil bundle:nil];
[self presentModalViewController:profile2 animated:YES];
[profile2 release];
}break;
default:
break;
}
}
and i Already imported the .h file of Profile Class..
so what's wrong !!!!
Thanks.
i don't understand you question perfectly hope this will help you.
- (IBAction)SegmentControll:(id)sender {
if (SegmentControll.selectedSegmentIndex==0) {
//your main view
}
if (SegmentControll.selectedSegmentIndex==1) {
//your Profile view
}
}
Do you want to switch users to profile view only after Successfully finishing registration/login otherwise show alert ?
then you may try this :
in your .h file
NSString *count;
in your .m file
#Synthesize count;
in your ViewdidLoad
count=#"1";
//so here default value of count is 1
// after Successfully finishing registration/login make count =2
count=#"2";
In your SegmentControl Action make this condition :
- (IBAction)SegmentControll:(id)sender
{
if (SegmentControll.selectedSegmentIndex==0)
{
if (count isEqualToString:#"2") {
//your main view
}
else
// alert for login/Register
}
if (SegmentControll.selectedSegmentIndex==1) {
//your Profile view
}
if (SegmentControll.selectedSegmentIndex==2) {
//your Register view
}
}
I have read the Apple docs - http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/TabBarControllers/TabBarControllers.html#//apple_ref/doc/uid/TP40007457-CH102-SW1 about creating TabBar programmatically. I want to detect the TabBar selection so I have used following delegate methods. I am not sure why but these methods don't get fired when I change the Tabs on my iPhone. Could anyone please provide some thought on what's going wrong here. It would be really helpful. Thanks.
- (BOOL)tabBarController:(UITabBarController *)tbController shouldSelectViewController:(UIViewController *)viewController
{
if (viewController == [tbController.viewControllers objectAtIndex:3] )
{
// Enable all but the last tab.
return NO;
}
return YES;
}
- (void)tabBarController:(UITabBarController *)tbController didSelectViewController:(UIViewController *)viewController {
if (viewController == [tbController.viewControllers objectAtIndex:self.appTabs.count] )
{
//do some action
}
}
Did you forget to set the delegate when you created the UITabBarController?
someTabBarController.delegate = self;