Why I am unable to push viewcontroller to the next viewcontroller? - iphone

I am working on sockets in objective-c so i wrote a function for getting response of server when my condition comes true i want to push to the next view controller but it is not pushing or presenting plz help
some code is given here
this is my function
void receiveData(CFSocketRef s,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void *info)
{
LoginViewController *lvc = [[LoginViewController alloc] init];
char *buffer = (char *)CFDataGetBytePtr((CFDataRef)data);
if (strstr(buffer, "LCNF|ACPT") == NULL)
{
NSLog(#"%#",data);
[lvc alert];
}
else
[lvc goToWatchList];
}
my "goToWatchlist" method is:
-(void)goToWatchList
{
WatchListViewController *wlController = [[WatchListViewController alloc] initWithNibName:#"WatchListViewController" bundle:nil];
[self presentModalViewController:wlController animated:YES];
[wlController release];
}
Thanx in advance

I have done something very similar before. Are you sure it even reaches your [lvc goToWatchList];
within receiveData? Also check that your reading from socket is not blocking the thread!
Also check your xib file - if this cannot be found it won't appear either... (Ups - already been mentioned while I was typing...)

Make sure this is happening on the main thread. Also make sure that wlController is not nil after the init message in case the nib cannot be found or there is a problem with it.
You create a new LoginViewController here:
LoginViewController *lvc = [[LoginViewController alloc] init];
But I don't see where you are adding that to a view. You push your WatchListViewController onto that, but it can't appear because its parent (the LoginViewController) is not showing up. Yes, the loadview on LoginViewController -(void)loadView will be called because you are adding something to it (the WatchViewController), but since that view isn't being displayed, it doesn't need to load the LoginViewController's view.
Try adding this code to the end of receiveData:
[[[UIApplication sharedApplication] keyWindow] addSubview:lvc.view];
If that doesn't work, try changing to the goToWatchListFunction to present the modal view controller on the [[UIApplication sharedApplication] keyWindow].

Related

Can I change the ViewController that calls presentViewController?

I have a ViewController, VC1a, that presents VC2:
VC1a -> presentViewController: VC2
Is it possible to change VC1a into VC1b so that when dissmissViewControllerAnimated is called, it animates to VC1b instead of VC1a?
The reason I ask is because I want to return to a different screen without it animating back to VC1a. This relates to portrait/landscape changes.
Warning. This is potentially a bad/confusing UI choice for your users. But if you must...
You may be able to put VC1a inside a UINavigationController and modify the navigation stack while VC2 is in the foreground. Something like:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
NSMutableArray *navigationStack = [[NSMutableArray alloc] init];
for (UIViewController *viewController in self.navigationController.viewControllers)
{
if (viewController != self.navigationController.viewControllers.lastItem)
{
[navigationStack addObject:viewController];
}
else
{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
}
}
self.navigationController.viewControllers = navigationStack;
}];
or possibly a better idea:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
[self.navigationController popViewControllerAnimated:NO];
[self.navigationController pushViewController:viewControllerToSwapIn animated:NO];
}];
OK, I implemented a Container view controller with two children - one for portrait, one for landscape and this took care of my problem.
I have spent days trying to figure out how to handle rotation correctly within iOS6 and I didn't realise there was a bug in rotating UITableViewController when pushed from a UINavigationController.
Thanks for the response #paulrehkugler - I was getting pretty desperate when I asked this question. There just doesn't seem to be any good examples of how to handle orientation changes while UINav/TableViewControllers are presented from a main view. I certainly wasn't wanting to implement such a hack.

InitWithName Execution Before ViewDidLoad Possible?

I'm trying to move an NSString between two View Controllers and after searching around all convoluted ways, the easiest and most straight-forward way I want to get used to was to write an initWithName function in the Receiving VC and calling it in the Sending VC. It does move it successfully but I want it to get executed before ViewDidLoad loads the textViewer so that it shows right after the tab button is pressed. Here's the code from the sending VC:
- (void)textViewDidEndEditing:(UITextView *)textView
{
if ([textView.text isEqualToString: #""]) {
textView.text = #"*Paste the machine code in question here*";
}
SecondViewController *theVCMover = [[SecondViewController alloc] initWithName: textView.text];
[self.navigationController pushViewController:theVCMover animated:YES]; //Is this really necessary if I'm not going to segue it directly, I'm just waiting for the user to press the next tab
gotItLabel.text = #"Got it! Ready for action...";
}
And here's the code on the receiving VC:
- (id)initWithName:(NSString *)theVCMovee {
self = [super initWithNibName:#"SecondViewController" bundle:nil];
if (self) {
rawUserInput = theVCMovee;
CleanerText.text = rawUserInput;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
CleanerText.text = rawUserInput;
NSLog(#"Got the other tab's text and it's %# ", rawUserInput);
}
Your code is mostly fine, but you'll find that as you have more complex view controllers that you won't necessarily want to write custom initializers to do every bit of property setting. Note that if CleanerText is a UI element that you're loading from your nib, it doesn't help to set CleanerText.text in your init method—it's not loaded until -viewDidLoad is called.
You don't have to do everything in init, though, if you declare properties for rawUserInput or other variables you want to set. You can then just go:
SecondViewController *theVCMover = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
theVCMover.rawUserInput = textView.text;
theVCMover.otherProperty = otherValue;
....
And the rest of your code works the same.
You can't (reliably) call methods on an instance until init has finished executing, so this pattern is "safe" and is how it's supposed to work.

Call method in viewDidAppear

I've set up a void method which is called from another class if the user touches the button.
However, I got this error with "whose view is not in window hierarchy" and then I found this: whose view is not in the window hierarchy. I just want to call the method below but I got this error and it doesn't show me the navigatoncontroller. It says Warning: Attempt to present <UINavigationController: 0xae34f10> on <ViewController: 0xae1f200> whose view is not in the window hierarchy!
I don't know if this is possible to call the method from the viewDidAppear or from somewhere that it only works if the button was tapped on the other view before. If I call a NSLog in the method it shows me the NSLog in the output. Only the presenting of the navController doesn't seems to work. I would be happy if someone could help me with this.
My method:
- (void) launchGalleryView
{
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set browser options.
browser.wantsFullScreenLayout = YES;
browser.displayActionButton = NO;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:browser];
NSMutableArray *photos = [[NSMutableArray alloc] init];
MWPhoto *photo;
photo = [MWPhoto photoWithFilePath:[[NSBundle mainBundle] pathForResource:#"calculator" ofType:#"jpg"]];
photo.caption = #"The calculator is soo beauteful...";
[photos addObject:photo];
self.photos = photos;
[self presentModalViewController:navController animated:YES];
}
Just forgot to say: The MWPhotoprowser is a class which actually does't matter.
Thanks in advance.
The error message is pretty clear -- you're trying to present the controller from this class, but the class that has the button you pressed is the one whose view is in the view hierarchy. You either need to present it from the class with the button, or get back to this class however you're doing that, and then call it after viewDidAppear.
i checked your project.. wasn't able to sort out the proper issue..
but i tried a hack and it worked..
replace this line with
[self presentModalViewController:navController animated:YES];
this
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentModalViewController:navController animated:YES];

unable to switch from multiple views

I have a simple app with only location services and 3 (almost empty) different views, and from some reason I can't get from view 1 to view 2 - app crashes and I get an exception. View 1 is the original .xib file, the two others are just views that I added later. It's weird cause I can switch between all of them (1->3, 2->1, 2->3, etc..) just not from 1->2.
I use this code in #1 view controller m. file:
- (IBAction) switchToMaps : (id)sender //this is the one that doesnt work
{
MyMap *mapsView = [[MyMap alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:mapsView animated:YES];
}
- (IBAction) switchToThird : (id)sender
{
ThirdView *third = [[ThirdView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:third animated:YES];
}
and as another example, here is the code from the 2nd view controller (MyMaps.m):
- (IBAction) switchBack : (id)sender
{
LastLocationViewController *firstView = [[LastLocationViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:firstView animated:YES];
}
- (IBAction) switchFront : (id)sender
{
ThirdView *lastView = [[ThirdView alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:lastView animated:YES];
}
I know it's super vague, but any ideas what can cause this? I have no idea how to debug this...I even put breakpoints at the beginning of each IBAction method, and when it crashes, it doesnt even stop there....before I added this code, this app (which has only location) worked totally fine.
Any ideas?? Thanks!!
if your view does not load from any nib file then you should do like
MyMap *mapsView = [[MyMap alloc] init];
and
ThirdView *lastView = [[ThirdView alloc] init];
and in your back method
- (IBAction) switchBack : (id)sender
{
// LastLocationViewController *firstView = [[LastLocationViewController alloc] initWithNibName:nil bundle:nil]; // because you are allocating new memory to your last view
// [self presentModalViewController:firstView animated:YES];
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction) switchFront : (id)sender
{
// ThirdView *lastView = [[ThirdView alloc] initWithNibName:nil bundle:nil];
// [self presentModalViewController:lastView animated:YES];
[self dismissModalViewControllerAnimated:YES];
}
My hunch is that you're throwing an exception because
MyMap *mapsView = [[MyMap alloc] initWithNibName:nil bundle:nil];
is failing to load a nib. Without seeing your console output it's impossible to say for sure. So a few things to try:
Comment out [self presentModalViewController:mapsView animated:YES];, see if it still crashes.
Explicitly name the nib you expect to load. The nib loader assumes the nib is named exactly the same as the view controller if you pass in nil. So if you don't have a match, you'll end up with an exception (Like this [[MyMap alloc] initWithNibName:#"NibNameWithoutExtension" bundle:nil];)
Set a breakpoint at [self present... and then hover your mouse over "mapsView" after execution pauses. If the popup thing shows you mapsView is nil, you know your trouble is trying to pass a nil object to -presentModalViewController:animated:. If your breakpoint never hits because you throw an exception first, well, there you go, the trouble is a line above.
edit:
One more thing. If your nib has a button that's wired to an action that no longer exists, that would definitely get you in trouble. Inspect each button and make sure no actions are labeled in yellow, indicating a mismatch between the button's target and the actions it's reporting to IB. This would definitely account for the breakpoint behavior you described.

Presenting a modal view controller when loading another ViewController

Before the user can use my application he has to login. After he logged in, the database is built because I need information from the server to build it.
Therefore my root ViewController is the LoginViewController which presents the actual application (a navigationController stack) modally on successful login.
If the user is already logged in on application launch (I am storing the credentials with NSUserDefaults) the LoginViewController should present the application immediately. Therefore I overwrote the method:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSInteger userId = [[NSUserDefaults standardUserDefaults] integerForKey:#"selfUser"];
if (userId != 0) {
//[self performSelector:#selector(presentMainViewController) withObject:nil afterDelay:2];
[self presentMainViewController];
}
}
- (void)presentMainViewController {
mainViewController = [[MainViewController alloc] init];
mainViewController.managedObjectContext = managedObjectContext;
navigationController = [[UINavigationController alloc] initWithRootViewController:mainViewController];
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:NO];
}
The [self presentMainViewController]; is executed but the controller does not show up. If I use the line above it does work.
Where do I have to put the code to make it work?
The view stack might not be completely created when viewDidAppear is send. So you should use the perfomSelector:withDelay to queue the call on the run loop. In this way you can ensure that the view stack is build when your code runs.
Cheers!
I had a similar situation and I resolved by moving the code to viewWillAppear (instead of viewDidAppear). It may worth to try.