How to launch a different viewController on the second launch - ios

Here the code I have under the viewController.m
This code will run when a user selects a viewController
-(void)switchViews {
UIStoryboard *mainStory = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStory instantiateViewControllerWithIdentifier:schoolName];
[self presentModalViewController:vc animated:YES];
NSUserDefaults *defaultViewController = [NSUserDefaults standardUserDefaults];
[defaultViewController setObject:nil forKey:#"save"];
[defaultViewController synchronize];
}
This code will run on the second time the app is launched
-(void)loadNewView {
UIStoryboard *mainStory = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NSUserDefaults *newUserDefault = [NSUserDefaults standardUserDefaults];
NSString *newVC = [NSString stringWithFormat:#"save", schoolName];
UIViewController *newViewController = [mainStory instantiateViewControllerWithIdentifier:newVC];
[self presentModalViewController:newViewController animated:YES];
}
Keeping in mind that schoolNameis a string
How can I run [self loadNewView] under the viewDidLoad but running it on the second time the app is launched?

You should do something like
id value = [[NSUserDefaults standardUserDefaults] objectForKey:#"save"];
if (value) {
UIViewController *vc = [mainStory instantiateViewControllerWithIdentifier:value];
[self presentModalViewController:vc animated:YES];
} else {
// first time logic
}
in your AppDelegate or wherever you have your navigation logic. You should not have that logic in viewDidLoad.

-(void)viewDidLoad {
[super viewDidLoad];
NSString *launchCount = #"LaunchCount";
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSInteger count;
if([userDefaults objectForKey:launchCount]) {
count = [userDefaults integerForKey:launchCount];
}
else {
count = 0;
}
count++; //increment the launch count
[userDefaults setObject:[NSNumber numberWithInt:count] forKey:launchCount];
[userDefaults synchronize];
if([userDefaults integerForKey:launchCount] >= 2) {
// Do your thang
}
}

on ViewDidLoad function do something like this
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedFirst"])
{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLauncheFirst"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self switchViews];
}
else
{
[[NSUserDefaults standardUserDefaults] setBool:No forKey:#"HasLauncheFirst"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self loadNewView];
}

Related

View controller won't return to previous view controller programmatically

The scenario is when the app first loads (controller A loads), it checks if an NSDefaultuser exist. If it does not exist then it sends it to (Controller B). In controller B the user enters his/her username then clicks ok. Now, NSDefault is saving the username and it should also redirect it back to the main view controller. Here is the code:
if([Username.text isEqual: #""]) {
[self showOkAlert:#"Username required"];
}
else if([Password.text isEqual:#""]) {
[self showOkAlert:#"Password required"];
}
else {
//suppose that login was successfully.
[self SaveCredentials];
NSString * storyboardName = #"MainStoryboard";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"LatestNews"];
[self presentViewController:vc animated:YES completion:nil];
}
Controller A:
- (void)LoadCredentials {
//load username
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *username = [defaults objectForKey:#"User"];
if(!username) {
[self showAlert:#"user does not exist"];
[self dismissViewControllerAnimated:YES completion:nil];
NSString * storyboardName = #"MainStoryboard";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"Login"];
[self presentViewController:vc animated:YES completion:nil];
}else{
[self showAlert:#"user exists"];
// for testing purposes I want it to reset when user logged in. Just so I know it resets. Later this method will be called from logout button.
[self resetUsernameWhenLogout];
}
}
-(void)resetUsernameWhenLogout {
//reset username when logout
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [defaultsDictionary allKeys]) {
[[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)viewDidLoad
{
[self LoadCredentials];
}
There are a couple of possibilities here; Firstly, iOS8 seems to instantiate the VC's a lot earlier than in iOS7, so the Navigation tree isn't complete in viewDidLoad, You should only use viewDidLoad for additonal initialization. Try moving your code [self LoadCredentials];
} to viewWillAppear.
Secondly, if you have a nav controller, you should be adding the new VC to the nav tree via the nav controller. If this is the case, try the code below.
if([Username.text isEqual: #""]) {
[self showOkAlert:#"Username required"];
}
else if([Password.text isEqual:#""]) {
[self showOkAlert:#"Password required"];
}
else {
//suppose that login was successfully.
[self SaveCredentials];
//This does not work - I receive a thread error not sure how to debug it
UIStoryboard *storyBoard = self.storyboard;
UIViewController *targetViewController = [storyBoard instantiateViewControllerWithIdentifier:#"LatestNews"];
UINavigationController *navController = self.navigationController;
if (navController) {
[navController pushViewController:targetViewController animated:YES];
}
}

Making a View for the first use of an app

I wish to make an app that, when the user opens it for the first time he selects his country from a picker in order to make his flag appear on the main screen. If the user closes the app and opens it again I want the app to start the menu screen with his flag on it directly.
I am using the following code now but it doesn't work at all. Every time the app is opened it takes him to the picker VIew (TappViewController)
- (void)viewDidLoad
{
[super viewDidLoad];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"FirstLaunch"]) {
secViewController *menu = [[secViewController alloc] init];
[self presentViewController:menu animated:YES completion:^{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];}];
}
else{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"FirstLaunch"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Change your code like this:
- (void)viewDidLoad
{
[super viewDidLoad];
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"isPickerOpened"]) {
secViewController *menu = [[secViewController alloc] init];
[self presentViewController:menu animated:YES completion:^{
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"isPickerOpened"];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
}
}

NSUserDefault for a simple game

I'm creating a simple game app.
When the user click on the first button and the int click is 0, the he can click on the second button, and so on.
If the user firstly click on the second button and then on the first, his lifes will decreasing.
I'm having problems when the user reaches 0 lifes and the View returns on the first page.
Then when I click on the button to play again, I have 0 lifes and don't 3!
Here is my code:
#implementation livello1
int click=0;
int lifes=3;
-(void)updateLifes:(int)lifes{
if (lifes==1){
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
[standardDefaults setObject:#"1" forKey:#"UserLifes"];
[standardDefaults synchronize];
[self showLifes];
livello1 *livello1view = [[livello1 alloc] initWithNibName:nil bundle:nil];
livello1view.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:livello1view animated:YES completion:nil];
}
else if (lifes==2){
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
[standardDefaults setObject:#"2" forKey:#"UserLifes"];
[standardDefaults synchronize];
[self showLifes];
livello1 *livello1view = [[livello1 alloc] initWithNibName:nil bundle:nil];
livello1view.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:livello1view animated:YES completion:nil];
}
else if (lifes==3){
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
[standardDefaults setObject:#"3" forKey:#"UserLifes"];
[standardDefaults synchronize];
[self showLifes];
livello1 *livello1view = [[livello1 alloc] initWithNibName:nil bundle:nil];
livello1view.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:livello1view animated:YES completion:nil];
}
else if (lifes==0){
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
lifes=3;
[self showLifes];
[standardDefaults setObject:#"3" forKey:#"UserLifes"];
[standardDefaults synchronize];
gioca *giocaview = [[gioca alloc] initWithNibName:nil bundle:nil];
giocaview.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:giocaview animated:YES completion:nil];
}
}
-(void)showLifes{
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
if ([[standardDefaults stringForKey:#"Userlifes"] isEqualToString:#"1"]) {
lifes=1;}
if ([[standardDefaults stringForKey:#"Userlifes"] isEqualToString:#"2"]) {
lifes=2;}
if ([[standardDefaults stringForKey:#"Userlifes"] isEqualToString:#"3"]) {
lifes=3;}
lifesLabel.text = [NSString stringWithFormat:#"%i",lifes];
}
- (IBAction)press1:(UIButton *)button1{
if ((button1.selected=YES && click==0)){
click=1;
}
else{
lifes=lifes-1;
click=0;
[self updateLifes:(lifes)];
}
}
- (IBAction)press2:(UIButton *)button2{
if ((button2.selected =YES) && click==1){
click=2;
}
else{
lifes=lifes-1;
click=0;
[self updateLifes:(lifes)];
}
}
- (void)viewDidLoad{
[super viewDidload];
[self showLifes];
}
Create another button for "Play Again" and link it to -(IBAction)buttonPressed:(UIButton *)playAgain and in that function reset the value of life to 3. And you don't need to pass lifes as it is a global variable (though that is not a very good practice). Though I am not really sure about your logic/ implementation for the click, you can use the following (slightly optimised) code :
#implementation livello1
int click=0;
int lifes=3;
-(void)updateLifes{
if (lifes!=0) {
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
[standardDefaults setInteger:lifes forKey:#"UserLifes"];
[standardDefaults synchronize];
[self showLifes];
livello1 *livello1view = [[livello1 alloc] initWithNibName:nil bundle:nil];
livello1view.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:livello1view animated:YES completion:nil];
}
else {
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
lifes=3;
[self showLifes];
[standardDefaults setObject:#"3" forKey:#"UserLifes"];
[standardDefaults synchronize];
gioca *giocaview = [[gioca alloc] initWithNibName:nil bundle:nil];
giocaview.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:giocaview animated:YES completion:nil];
}
}
-(void)showLifes{
NSUserDefaults *standardDefaults = [NSUserDefaults standardUserDefaults];
lifesLabel.text = [NSString stringWithFormat:#"%i",[standardDefaults integerForKey:#"Userlifes"]];
}
- (IBAction)press1:(UIButton *)button1{
if ((button1.selected=YES && click==0)){
click=1;
}
else{
lifes=lifes-1;
click=0;
[self updateLifes];
}
}
- (IBAction)press2:(UIButton *)button2{
if ((button2.selected =YES) && click==1){
click=2;
}
else{
lifes=lifes-1;
click=0;
[self updateLifes];
}
}
- (IBAction)buttonPressed:(UIButton *)playAgain{ //the new function
lifes = 3;
click = 0;
[self updateLifes];
}
- (void)viewDidLoad{
[super viewDidload];
[self showLifes];
}
on playAgain Button click, setLife counter to 3.

Storyboard with differing initial view controllers [duplicate]

This question already has answers here:
Conditionally start at different places in storyboard from AppDelegate
(10 answers)
Closed 9 years ago.
I have a problem with launching different views.
I have some kind of a tutorial. Therefore I have set this code in didFinishWithLaunchOptions:
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]) {
// Schon mal geöffnen. Kein Tutorial
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Wurde das erste mal geöffnet. Tutorial anzeigen!
}
But I don't really know how to make it actually open the different views now. Couldn't find any documentation on it :(
I just want to open a tutorial viewController if its the first launch and if its not the initial viewController.
Please take a look at this this question. I modified the answer to fit your case, you should put the following code in application:didFinishLaunchingWithOptions:
NSString *storyboardIdentifier;
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]) {
// Schon mal geöffnen. Kein Tutorial
storyboardIdentifier = #"mainViewController";
} else {
// Wurde das erste mal geöffnet. Tutorial anzeigen!
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
storyboardIdentifier = #"tutorialViewController";
}
UIViewController *rootViewController = [[[[self window] rootViewController] storyboard] instantiateViewControllerWithIdentifier:storyboardIdentifier];
[[self window] setRootViewController:rootViewController];
UIViewController *controller = nil;
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"]) {
controller = [HomeViewController alloc] initWithNibName: #"HomeViewController" bundle: nil];
}
else {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
// Wurde das erste mal geöffnet. Tutorial anzeigen!
controller = [TutorialViewController alloc] initWithNibName: #"TutorialViewController" bundle: nil];
}
self.window.rootViewController = controller;
For instantiating a viewcontroller from a storyboard the following will work:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
TutorialViewController *controller = (TutorialViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"TutorialViewControllerID"];
Remember to set a ID for the viewcontroller in your storyboard.

How to update UITextView after login

I am trying to integrate Facebook to my iOS app with ARC. To use FB SDK, I have disabled ARC with "-fno-objc-arc" for those files. However, it still have EXC_BAD_ACCESS error and I need to change
#property(nonatomic, assign) id<FBSessionDelegate> sessionDelegate;
to
#property(nonatomic, retain) id<FBSessionDelegate> sessionDelegate;
The login is working now but the UITextView is not updated after login
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]
&& [defaults objectForKey:#"FBExpirationDateKey"]) {
[delegate facebook].accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
[delegate facebook].expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
if (![[delegate facebook] isSessionValid])
{
[[delegate facebook] authorize:nil];
}
}
- (void)fbDidLogin
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[[delegate facebook] accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[[delegate facebook] expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[[delegate facebook] requestWithGraphPath:#"me" andDelegate:self];
}
- (void)request:(FBRequest *)request didLoad:(id)result
{
if ([result isKindOfClass:[NSArray class]]) {
result = [result objectAtIndex:0];
}
if ([result objectForKey:#"name"]) {
self.uitextview.text = [result objectForKey:#"name"];
}
}
I have checked that "[result objectForKey:#"name"]" will return a result but "self.uitextview" is not recognized.
How do I update a UITextView after successful login?
Found out that the ViewController init in Appdelegate can't be used as shown in Facebook Hackbook sample.
Replace with the following declaration:
UITabBarController *tabBarController = (UITabBarController *) self.window.rootViewController;
ViewController *viewcontroller = [[tabBarController viewControllers] objectAtIndex:4];
http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1

Resources