Ok I have an application that uses tab controller. However before I want the tab controller to load up, I want the user to enter a screen which allows them to enter their phone number first as I need to save the users phone number for use in the application. I save the number to the application like this.
[[NSUserDefaults standardUserDefaults] setInteger:1234 forKey:#"PhoneNumber"];
Basically when they first enter application, a window will open which will allow them to store enter their number in text field and it saved using the NSuserDefaults.
In the appDelegate, I have an if statement to check if a value is stored or not like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
NSInteger phoneNumber=[[NSUserDefaults standardUserDefaults] integerForKey:#"PhoneNumber"];
if(phoneNumber == 0){
//So this is the window which allow them to enter their phone number
UIViewController *phoneNumberVC = [[PhoneNumberVC alloc] initWithNibName:#"PhoneNumber" bundle:nil];
UIViewController *phoneNumberRootVC = [[UINavigationController alloc] initWithRootViewController:phoneNumberVC];
self.window.rootViewController = phoneNumberRootVC;
[self.window makeKeyAndVisible];
}else{
//Code here sets up tab controller and all the tabs etc
}
}
Now the code works fine, except for the fact that after the number is saved, I have to exit the simulator, and run it again, and then the tab screens appear. However, I want the tab controller to load up a soon as the user has pressed the button in the phone number screen to save the number. Current method in the phone number screen is this:
-(IBAction)testing{
NSString *st = [phoneTF text];
NSInteger pn = [st intValue];
NSString *display = [NSString stringWithFormat:#"%i", pn];
[[NSUserDefaults standardUserDefaults] setInteger:pn forKey:#"PhoneNumber"];
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Warning"
message:display
delegate:self
cancelButtonTitle:#"Okay"
otherButtonTitles:nil];
[alert show];
}
The alert is just for testing purposes. So after the button is pressed, I want the tab controller to load up in the app delegate. Is there anyway I can refresh the application or the app delegate?
Would be very grateful if someone could point me in the right direction!!!
EDIT
Tried
[self.navigationController pushViewController:app.tabBarController animated:YES];
But as the tabBarController is not initialised yet, it won't run
Console error
Application tried to push a nil view controller on target <UINavigationController: 0x8056d40>.
So I need to run the AppDelegate again, so the tab controller and all its views will be initialised
replace
UIAlertView * alert = [[UIAlertView alloc] initWithTitle:#"Warning" message:display
delegate:self cancelButtonTitle:#"Okay" otherButtonTitles: nil];
[alert show];
with code that asks the navigation controller to switch to the other view you want:
YourOtherViewController *yourOtherViewController = [[YourOtherViewController alloc] init];
[self.navigationController pushViewController:yourOtherViewController animated:YES];
Edit
If you want to access the AppDelegate from phoneNumberVC, you can do something like the following:
if(phoneNumber == 0){
UIViewController *phoneNumberVC = [[PhoneNumberVC alloc] initWithNibName:#"PhoneNumber" bundle:nil];
phoneNumberVC.appDelegate = self; // add this property to PhoneNumberVC
UIViewController *phoneNumberRootVC = [[UINavigationController alloc] initWithRootViewController:phoneNumberVC];
self.window.rootViewController = phoneNumberRootVC;
} else {
[self setUpTabViewController]; // add this function
}
[self.window makeKeyAndVisible];
And in PhoneNumberVC something like:
[self.appDelegate setUpTabViewController];
Related
In my window base application I need to navigate to informationview from my appdelegate when i click on alert view button.
alert view works with NSlog.
But i need to push to the other view for this purpose i used
[self.navigationController pushViewController:info animated:YES];
but it doesn't pushes. just nslog only prints
- (void)applicationDidBecomeActive:(UIApplication *)application
{
//To count the number of launches
NSInteger i = [[NSUserDefaults standardUserDefaults] integerForKey:#"numOfCalls"];
[[NSUserDefaults standardUserDefaults] setInteger:i+1 forKey:#"numOfCalls"];
NSLog(#"the number of active calls are %d",i%3);
if(i%3==0 && i!=0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"you might prefer MedChart+" message:#"Get it now for more options" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert show];
[alert release];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"canceled");
}
else if (buttonIndex == 1)
{
NSLog(#"Pushed to the information view ");
InformationViewCotroller *info = [[InformationViewCotroller alloc]initWithNibName:#"InformationViewCotroller" bundle:nil];
[self.navigationController pushViewController:info animated:YES];
}
}
(dont consider 'i' values it is part of my logic).
Thanks in advance
Before Navigate to any viewController , set the RootController for your navigationController of appDelegate.
Add navigationController.View as subview of window.Then your root controller will be the first ViewController.from there you can push to any viewController.
I'm having a terrible time getting a UIAlertView to work within my custom NSObject class. In the research I've done it appears it should be possible but here's what I've run into.
First, here's my code:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(#"clickedButtonAtIndex: %d", buttonIndex);
}
-(void)testAlertView {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"List Contains Items"
message:#"List contains items. Remove all items & delete?"
delegate:self
cancelButtonTitle:#"No"
otherButtonTitles:#"Yes", nil];
[alertView show];
}
If I set the delegate to self this code crashes as soon as I tap a button. If I set it to nil clickedButtonAtIndex is never called. I've tried with and without using the <UIAlertViewDelegate>.
I know someone will ask 'why are you doing this in NSObject instead of in your UIViewController?'. Primarily because I want to separate this code out so I can use it from multiple places in my app. But also because this is a small piece of a larger block of logic that makes sense to be on it's own.
Any ideas what I'm doing wrong?
Thanks,
Rich
I had the same problem using ARC. The root of the problem was the same. I solved it by putting my custom NSObject into a "strong" property to make sure the object exists as long as the calling object (an UIVIewCOntroller in my case) exists, so when the delegate of my alert view is called I still have my custom object around and the delegate method works fine.
Add the NSObject as strong property:
#import "Logout.h" // is NSObject
.
.
.
#property (nonatomic, strong) Logout *logout;
Then you will get the delegatemethods called in your NSObject.
Don´t forget to register the delegate for the UIAlertView:
#interface Logout () <UIAlertViewDelegate>
and in your method:
UIAlertView *a = [[UIAlertView alloc] initWithTitle:#"title"
message:#"message" delegate:self cancelButtonTitle:#"cancel"
otherButtonTitles:#"ok", nil];
[a show];
How To Present An Alert View Using UIAlertController When You Don't Have A View Controller. Detail description.
Yes, you can only use UIAlertController only in UIViewController classes. So how can we do it in NSObject classes. If you see the description link given above you will get to the answer. To summarise in a line for the above description: Create a new window above the the current window. This new window will be our viewController where we display alert. So using this viewController you can call the method [presentViewController: animated: completion:].
Answer:
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow* window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = [UIViewController new];
window.windowLevel = UIWindowLevelAlert + 1;
NSString *msg=#“Your mssg";
UIAlertController* alertCtrl = [UIAlertController alertControllerWithTitle:#“Title" message:msg preferredStyle:UIAlertControllerStyleAlert];
[alertCtrl addAction:[UIAlertAction actionWithTitle:NSLocalizedString(#"Yes",#"Generic confirm") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
// do your stuff
// very important to hide the window afterwards.
window.hidden = YES;
}]];
UIAlertAction *cancelAction= [UIAlertAction actionWithTitle:#"cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
window.hidden = YES;
}];
[alertCtrl addAction:cancelAction];
//http://stackoverflow.com/questions/25260290/makekeywindow-vs-makekeyandvisible
[window makeKeyAndVisible]; //The makeKeyAndVisible message makes a window key, and moves it to be in front of any other windows on its level
[window.rootViewController presentViewController:alertCtrl animated:YES completion:nil];
});
I use Apple's Reachability class and it's working fine using an alert to tell the user that the connection is not available or the connection is lost. However, I want to change the alert to something more visual. I want to load a nib that tells the user no active connection is present but the nib is not loading. I also tried loading my other nibs but it also doesn't load the nib.
- (BOOL) checkNetworkStatus:(NSNotification *)notice
{
// called after network status changes
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(#"The internet is down.");
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"No Internet Connection" message:#"You are currently not connected to a WI-FI or cellular Data.\nPlease make sure you are connected." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alert show];
[alert release];
//NoConnection *noConn = [[NoConnection alloc] initWithNibName:#"NoConnecton" bundle:nil];
//[self presentModalViewController:noConn animated:NO];
//[NoConnection release];
self.isConnected = NO;
return NO;
break;
}
//more cases.........
the alert part is working just fine but the part for loading the nib is not. can you tell me whats wrong here? I'm calling this function in viewWillAppear. Thanks!
You can do the following:
if ( ! isConnected )
{
NoConnection *noConn = [[NoConnection alloc] initWithNibName:#"NoConnecton" bundle:nil];
[self presentModalViewController:noConn animated:NO];
[NoConnection release];
}
The code you have presented should work, sow the problem must be somewhere else probably in the nib - linking, you might have forgot to link something to the nib file.
try this
[self.navigationController presentModalViewController:noConn animated:YES];
Does your nib has NoConnection as a File's Owner (I guess NoConnection is a subclass of UIViewController, check it. I'll call this NoConnectionViewController bellow because you should name it like that for no mistake) ?
Is the file's owner view property linked with the graphical view ? Check it.
Are you working without status bar at top of the window ? That could be a problem.
Are your here inside a modalViewController ? If yes, your code won't work, you must use instead :
NoConnectionViewController* nextWindow = [[NoConnectionViewController alloc] initWithNibName:#"NoConnecton" bundle:nil]; // Check your nib name here, seems to be a mistake
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextWindow];
[self presentModalViewController:navController animated:YES];
[navController release];
[nextWindow release];
You need to use the delegate method of alert view
#pragma mark - AlertView Delegates
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 1)
{
NoConnection *noConn = [[NoConnection alloc] initWithNibName:#"NoConnecton" bundle:nil];
[self presentModalViewController:noConn animated:NO];
[NoConnection release];
}
}
don't forget to assign tag value of alertView to 1.
and also dont forget to conforms to the UIAlertViewDelegate protocol
Happy Coding :)
Dear all, I have a navigation-based app with about 60 views.
I have run with the following :
1. Build and analyse : bulid is successful with no complains.
2. Instruments allocation and leaks : no leaks.
However, the app crashed in iPhone or iPad but works fine in simulator.
The crash occurs at around 50th view.
There is no crash reports but I do see LowMemory.log in the crashreporter folder.
I have upgraded my iphone and ipad to 4.2
Does anyone have ideas what could be wrong?
I have been reading and troubleshooting for a week.
Thank you for all the replies.
My app has a root view called contentViewController and users can navigate to 4 quizzes from here.
This is the code I use to return to my root view.
- (void)goHome {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Warning"
message: #"Proceed?"
delegate: self
cancelButtonTitle:#"Yes"
otherButtonTitles:#"No",nil];
[alert show];
[alert release];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
[[self navigationController] setNavigationBarHidden:NO animated:YES];
if (buttonIndex == 0) {
NSArray * subviews = [self.view subviews];
[subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
self.view = nil;
if (self.contentViewController == nil)
{
ContentViewController *aViewController = [[ContentViewController alloc]
initWithNibName:#"ContentViewController" bundle:[NSBundle mainBundle]];
self.contentViewController = aViewController;
[aViewController release];
}
[self.navigationController pushViewController:self.contentViewController animated:YES];
}
}
Sample code for pushing views :
-(IBAction) buttonArrowClicked:(id)sender {
NSURL *tapSound = [[NSBundle mainBundle] URLForResource: #"click"
withExtension: #"aif"];
// Store the URL as a CFURLRef instance
self.soundFileURLRef = (CFURLRef) [tapSound retain];
// Create a system sound object representing the sound file.
AudioServicesCreateSystemSoundID (
soundFileURLRef,
&soundFileObject
);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![[defaults stringForKey:#"sound"] isEqualToString:#"NO"]) {
AudioServicesPlaySystemSound (soundFileObject);
}
if (self.exercise2ViewController == nil)
{
Exercise2ViewController *aViewController = [[Exercise2ViewController alloc]
initWithNibName:#"Exercise2ViewController" bundle:[NSBundle mainBundle]];
self.exercise2ViewController = aViewController;
[aViewController release];
}
[self.navigationController pushViewController:self.exercise2ViewController animated:YES];
}
You will normally not run into memory problems when running under the simulator, so these errors are not automatically encountered on this platform.
The simulator does however have a feature where you can manually trigger a Low Memory event. If this is actually the cause of the crash on the device, then it might also be possible that you can trigger the same bug in the simulator in this way.
Sharing some code about how you push the view controllers will allow others to help you with this.
You can pop to root view controller more easily by doing:
[self.navigationController popToRootViewControllerAnimated:YES];
You are actually pushing a new instance of your root view controller in the code that you have shared.
I used to show a splash screen which in background load some data from web, I also check that if the location of the user is changed from one city to another city I want to show in alert to the user with the message that you are now in "CityName" would you like to see data from this city?
I have tabbed application and I have presented the splash screen as follow in the app delegate class.
SplashViewController *controller = [[SplashViewController alloc] initWithNibName:nil bundle:nil];
tabBarController.view.frame = [[UIScreen mainScreen] bounds];
controller.tabBarController = self.tabBarController;
[application setStatusBarStyle:UIStatusBarStyleBlackOpaque];
[window addSubview:controller.view ];
//[window addSubview:tabBarController.view ];
[self.tabBarController presentModalViewController:controller animated:YES];
[window makeKeyAndVisible];
[controller release];
Now when I show the alert screen it crash the application with "EXC_BAD_ACCESS" message and the stack trace show that _buttonClick is released in UIAlertView class.
Please advise what should I do, I also tried with UIActionSheet but the same problem with this thing too.
I think there is some problem with the model thing with the current view (SplashView).
Thanks in advance.
Are you trying to display your UIAlertView inside of your SplashViewController viewDidAppear? If not, I would try that first. I would also make sure you have your UIAlertView clickedButtonAtIndex method setup properly to try and trap what is going on.
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Your Location Has Changed"
message:#"Your location has changed since you last opened opened THEAPP. Would you like to refresh your data?" delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alert.tag = 1;
[alert show];
[alert autorelease];
Then for the clickedButtonAtIndex method:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
//--NSLog(#"You clicked button #%i",buttonIndex);
if (alertView.tag == 1){
if (buttonIndex == 0) {
//--NSLog(#"CANCEL");
} else if (buttonIndex == 1) {
//--NSLog(#"OK");
}
}
}
Doing all of this on a splash screen should be fine as long as you take into account the HIG's requirements for using the users location. Hope this helps!
I resolve this issue, the problem was that my Splash View was a modeled view and invoked by
[self.tabBarController presentModalViewController:controller animated:YES];
what I did that I shifted the data downloading to another view controller and there I can show alerts, and can handle that