I've tabbar controller with 6 to 7 tabs on it with customization allowed (means that the user can change the order of tab bar display). And tab 1,3,5,7 requires the user to login access before seeing any contents on the view.
I don’t know as to how to identify which tabbar requires login access (Can we create #protocal or something). And after the user logs in successfully. I don’t know how to select the last tabbar, which the user has touched on.
I was using appdelegate by confiming to UITabBarControllerDelegate in AppDelegate
-(BOOL)tabBarController:(UITabBarController *)aTabBar shouldSelectViewController:(UIViewController *)viewController {
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
BOOL hasValidLogin = [standardUserDefaults boolForKey:#"hasValidLogin"];
if (hasValidLogin == NO && /* I don't know to find a controller which requires login access*/) {
[LoginView showModal:viewController delegate:self];
return NO;
}
return YES;
}
pragma mark -
pragma mark LoginDelegate methods-
-(void)loginViewController:(LoginView *)loginViewController didLoginSuccess:NSString *)userName {
NSLog((#"%s [Line %d] "), __func__, __LINE__);
NSLog(#"userName = %#", userName);
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
[standardUserDefaults setBool:YES forKey:#"hasValidLogin"];
[standardUserDefaults synchronize];
[self.tabBarController setSelected:/* How do i find the last touched tabbar*/];
}
Any good practice,recipes and code snippet you can direct me is appreciated.
I was reading matt's iOS Recipes. But I couldn't find anything related to this one.
Focus on UITabBarDelegate didSelectItem. Keep track of the previously selected tab item. If the user is not authenticated, pop up your authentication screen and select the previously selected tab item. Here is an example.
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
switch ( item.tag ) {
case ME_TAB_BAR_TAG:
if ( [AppHelper checkAuthentication] ) {
[self showMe:YES];
} else if ( previousItem ) {
[tabBar setSelectedItem:previousItem];
return;
}
break;
case ITEMS_TAB_BAR_TAG:
[self showMe:NO];
break;
case CREATE_TAB_BAR_TAG:
if ( [AppHelper checkAuthentication] ) {
[self createNewItem];
} else if ( previousItem ) {
[tabBar setSelectedItem:previousItem];
return;
}
break;
}
previousItem = item;
}
Related
I am using CAPSPageMenu with 2 tabs. Now there is an button at right bar button. When ever i click that i have an view with one button called sayHello. Now when i click that button i needs to know which tab i was in. That bar button is for both tabs.But how can i check which tab was i am when i click on that sayHello.
code :
In my homevc i added that two tabs .
VC1, VC2..
And i tried in viewwillAppear added on bool in nsuserdefault and tried to fetch. But that bool is always coming as TRUE. Which ever tab i am - still the bool values i coming as true.Here is an code :
In vc1
-(void)viewWillAppear:(BOOL)animated {
userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setBool:TRUE forKey:#"fromVC1"]; // Tried true, YES also
NSLog(#"from vc1");
}
In vc2
-(void)viewWillAppear:(BOOL)animated {
userDefault = [NSUserDefaults standardUserDefaults];
[userDefault FALSE forKey:#"fromVC1"]; // Tried false, No also
NSLog(#"from vc1");
}
And i am checking like :
BOOL Val;
userDefault = [NSUserDefaults standardUserDefaults];
Val = [userDefault objectForKey:#"fromVC1"];
if (Val) {
NSLog(#"from VC1");
}else {
NSLog(#"from VC2");
}
But always its coming as True. Any idea how to get that ?Which tab i was i before. when i press my button sayHello.
- (void)didTapGoToLeft {
NSInteger currentIndex = self.pageMenu.currentPageIndex;
if (currentIndex > 0) {
[_pageMenu moveToPage:currentIndex - 1];
}
}
//
- (void)didTapGoToRight {
NSInteger currentIndex = self.pageMenu.currentPageIndex;
if (currentIndex < self.pageMenu.controllerArray.count) {
[self.pageMenu moveToPage:currentIndex + 1];
}
}
if you conform with delegate of CAPSPageMenu, you get the tab with the following two delegate methods.
// Optional delegate
- (void)willMoveToPage:(UIViewController *)controller index:(NSInteger)index {}
- (void)didMoveToPage:(UIViewController *)controller index:(NSInteger)index {}
for e.g
Intially, you nee to tell the compiler that your class implements the protocol:
#interface ViewController : UIViewController<CAPSPageMenuDelegate>
#property (nonatomic) CAPSPageMenu *pagemenu;
thereafter you need to conform the delegate
_pageMenu.delegate = self;
and finally access the delegate as your need.
(void)didMoveToPage:(UIViewController *)controller index:(NSInteger)index {
NSLog(#"controller: %#", controller);
NSLog(#"tabbed Index : %d", index);
}
for step by step intro : https://github.com/PageMenu/PageMenu/blob/master/README.md
I quite agree with the #Anbu.Karthik. Karthik implementation
But I would like to answer that you always get TRUE value when userDefault appears
Because you do not provide a full method context to read the userDefault Value.
So I don't know if it's due to the call life cycle, but if you try to write userDefault methods to viewDidAppear:(BOOL)animated, I'm sure you'll get the expected values.
Schematic code:
- (void)viewDidAppear:(BOOL)animated {
BOOL value;
NSUserDefaults* userDefault = [NSUserDefaults standardUserDefaults];
value = [userDefault objectForKey:#"fromVC1"];
}
I hope I can help you
I have a UISwitch set as the accessoryView in each of my TableView cells.
If I press my Confirm button, I want to save the state of each UISwitch with NSUserDefaults. Then when I leave and go back to that View Controller, I should be able to load those saved states which will be different for each cell (either on or off, as shown in image).
I'm almost there but I guess I am not sure how to save/load with the right indexPath.row so it's not working correctly. Right now it is just saving/loading one BOOL value only, so if I save one cell with the switch ON, then all of them will be ON, and vice versa.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
BOOL menuSwitchState = [[NSUserDefaults standardUserDefaults] boolForKey:#"menuItemSwitch"];
NSLog(#"Menu Switch State is: %#", menuSwitchState ? #"Yes": #"No");
[self.switchView setOn:menuSwitchState animated:YES];
}
UISwitch code in my cellForRowAtIndexPath:
// Add a UISwitch to the accessory view.
self.switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
cell.accessoryView = self.switchView;
self.switchView.tag = indexPath.row;
self.switchView.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"menuItemSwitch"];
[self.switchView addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
Switch action method which sets a BOOL:
- (void) switchChanged:(id)sender {
UISwitch *switchControl = sender;
NSLog(#"The switch's tag number is %ld", (long)switchControl.tag);
// NSLog(#"The switch is %#", switchControl.on ? #"ON" : #"OFF" );
if ([sender isOn])
{
self.switchIsOn = YES;
NSLog(#"THE SWITCH IS ON");
}
else
{
self.switchIsOn = NO;
NSLog(#"THE SWITCH IS OFF");
}
}
Confirm button that should save the state of the switch:
#pragma mark - UIBUTTONS
- (IBAction)onConfirmMenuButtonPressed:(id)sender
{
[self performSegueWithIdentifier:#"segueMenuToGettingStarted" sender:self];
//TODO: Save state of Switch.
if (self.switchIsOn == YES)
{
[[NSUserDefaults standardUserDefaults] setBool:self.switchView.on forKey:#"menuItemSwitch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
[ud setBool:NO forKey:#"menuItemSwitch"];
}
}
You save that value just like any other value you use in a table view -- in an array that's your data source. Given what you show in your image, your data source should be an array of dictionaries with keys for the menu item, price, and switch state. In cellForRowAtIndexPath, you would set the state of the switch based on the value ( a BOOL) in your array.
in your code, you just set one NSUserDefault value for the all items(now, looks like three), I think you must separate each kind of item, it means you must have the count of NSUserDefault same as the count of UISwitch, In UIViewController, you can hold the NSUserDefault values in an Array, when you change the switch, you changed the cell data, when you leave the ViewController, save the Array's values. Enter the ViewController, update the Array.
This is my first iOS app and at this moment I'm struggling with Acccount / Login transitions on my storyboard.
What I'm trying to do is, If there is no logged user, display the login, otherwise display the account menu (Edit profile, My savings, and Logout).
Actually I'm achieving with this code on my AccountMenuViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
if (![self isLogged]) {
[self presentLoginView];
}
}
#pragma mark - Login methods
- (BOOL)isLogged
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
return [[defaults objectForKey:#"loggedIn"] boolValue];
}
- (void)presentLoginView
{
[self performSegueWithIdentifier:#"LoginSegueId" sender:self];
}
When the user touch "Cancel login" I'm trying to redirect to my MainView, I've make a segue but the Tab Bar is not displayed.
And when the login is ok, Close the login view.
I want to know your advices and tips, What are the best practices with this scenario?
This is my Storyboard.
First you should either make the login screen your rootViewController and just push to main view if
[self isLogged]==YES
or have the Login presented in a model fashion with the main view as a root, that way instead of a segue you can just dismiss it and the main view will be present underneath. you can also have the main view push the login and just hide the nav bar and use 'cancel login' as a sort of '< back' button that you would see on the nav bar by using the popViewController method..... also you can simplify the method:
- (BOOL)isLogged
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
return [[defaults objectForKey:#"loggedIn"] boolValue];
}
can be :
- (BOOL)isLogged
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
return [[NSUserDefaults standardUserDefaults] boolForKey:#"loggedIn"];
}
hope i helped!
I have searched around and cannot find anything, help would be appreciated. I am very new to objective-C and Xcode.
In my app the player starts with 100 coins, this is represented in a label. When the user clicks a button to spend 10 coins, a popup box appears and asks 'are you sure', the user can click ok, or cancel.
If the user clicks 'ok' they spend 10 coins. At the moment, in the simulator when i'm in the same view everything is fine, the 100 goes down to 90 etc...
But when I go to another view and then back again, the coin amount goes back up to 100. This is the same when the user exits the app.
Here is my code:
.h file
//Coin
IBOutlet UILabel * coinCount;
.m file
int coinAmount = 100;
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"user pressed Cancel");
// Any action can be performed here
}
else
{
NSLog(#"user pressed OK");
coinAmount -= 10;
[coinCount setText:[NSString stringWithFormat:#"%d", coinAmount]];
NSString * string = [NSString stringWithFormat:#"%d", coinAmount];
//Save coin amount
NSString * saveCoinAmount = string;
NSUserDefaults * defaultsCoinAmount = [NSUserDefaults standardUserDefaults];
[defaultsCoinAmount setObject:saveCoinAmount forKey:#"saveCoinLabel"];
[defaultsCoinAmount synchronize];
}
}
That seems to save the new coin amount, so now when the user goes to another view and back i try and load the saved coin amount:
- (void)viewDidLoad
{
[super viewDidLoad];
//Coin Label
NSUserDefaults * defaultsLoadCoin = [NSUserDefaults standardUserDefaults];
NSString * loadCoinLabel = [defaultsLoadCoin objectForKey:#"saveCoinLabel"];
[coinCount setText:loadCoinLabel];
}
Any help would be greatly appreciated!
Your problem is that you are storing your coins in two places - an integer variable and the label. When you return to your view you restore the saved coin amount directly into the label, but when you perform the "purchase" you use the integer, which has been re-initialised to 100.
I also suggest you get out of the habit of using instance variables and use properties.
You should do something like this -
.m file
#interface MyClass () // Change this to suit your class name
#property NSInteger coinAmount;
#property (weak,nonatomic) IBOutlet UILabel *coinLabel;
#end
#implementation MyClass
- (void)viewDidLoad
{
[super viewDidLoad];
//Coin Label
NSUserDefaults * defaultsLoadCoin = [NSUserDefaults standardUserDefaults];
if ([defaultsLoadCoin objectForKey:#"coins] == nil) {
self.coinAmount=100;
[defaultsLoadCoin setInteger:self.coinAmount forKey:#"coins"];
}
else {
self.coinAmount = [defaultsLoadCoin integerForKey:#"coins"];
}
self.coinLabel.text=[NSString stringWithFormat:#"%ld",self.coinAmount];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"user pressed Cancel");
// Any action can be performed here
}
else
{
NSLog(#"user pressed OK");
self.coinAmount -= 10;
self.coinLabel.text=[NSString stringWithFormat:#"%ld",self.coinAmount];
//Save coin amount
NSString * saveCoinAmount = string;
NSUserDefaults * defaultsCoinAmount = [NSUserDefaults standardUserDefaults];
[defaultsCoinAmount setInteger:self.coinAmount forKey:#"coins"];;
[defaultsCoinAmount synchronize];
}
Your coinAmount property is not persistent through app launches or initialisations of the view controller in which it is created. You should consider persisting this value in database (like CoreData) or in NSUserDefaults.
My advice: start with basics (links to docs):
CoreData
NSUserDefaults
I have a storyboard in my app with my UISwitch element (checklist) and I am attempting to store the switch states so that if the user checks a few items and then leaves the page (modally) or closes the app with the Home key, the state of the UISwitch elements is remembered and the user can continue along with the checklist.
If an item is read and you turn the UISwitch off, the font turns red else the UISwitch is on and the font is White.
Everything seems to work (still learning OOP and Xcode 5) except if I back out of the page (leave modally) and then return the UISwitch elements are all On again. If I stop the simulator (or IPAD) and restart the app when I get to the page all UISwitch are ON again instead of what was selected being OFF.
If I use the Home button and return to the app the UISwitch elements are still in the state they were left.
In the .m file here is the viewDidLoad method for just one of the switches:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
self.SwitchFlipChart.on = ([[standardDefaults stringForKey:#"Switch1"] isEqualToString:#"On"]) ? (YES) : (NO);
}
and below is the IBAction method for the same UISwitch element
- (IBAction)SwitchFlipchart:(UISwitch *)sender{
if (SwitchFlipchart.on) {
LabelFlipchart.textColor = [UIColor whiteColor];
} else {
LabelFlipchart.textColor = [UIColor redColor];
}
SwitchFlipchart.hidden = YES;
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if (sender.tag == 0) {
if (sender.on == 0) {
[standardDefaults setObject:#"Off" forKey:#"Switch1"];
} else if (sender.on == 1) {
[standardDefaults setObject:#"On" forKey:#"Switch1"]; //removed f from fSwitch1
}
}
[standardDefaults synchronize];
}
Does it appear I am using the NSUserDefaults correctly or is it because I am reloading the page when stopping the Simulator or leaving the Page Modally?
Is there a better (sometimes easier is not better) way to work with NSUserDefaults and multiple UISwitch elements?
Is there a better way to retain UISwitch element state when loading a page after leaving it modally?
Is there a better way to store UISwitch states than the NSUserDefaults?
Replace your code with this
- (IBAction)SwitchFlipchart:(UISwitch *)sender{
if (SwitchFlipchart.on) {
LabelFlipchart.textColor = [UIColor whiteColor];
} else {
LabelFlipchart.textColor = [UIColor redColor];
}
SwitchFlipchart.hidden = YES;
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if (sender.tag == 0) {
if (sender.on == 0) {
[standardDefaults setObject:#"Off" forKey:#"Switch1"];
} else if (sender.on == 1) {
[standardDefaults setObject:#"On" forKey:#"Switch1"];
}
}
[standardDefaults synchronize];
}
Explantion :-
You are setting on for wrong key. The key should be same Switch1 for both condition. But you are using fSwitch1 for On state. Please check your code.