I am trying to implement ECSlidingViewController & I am using segues in my storyboards. I am having a problem where the MainViewController's viewDidLoad is being called twice and
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
is always getting set to null. More information.
LogIn Screen ( InitViewController ) ------through segue---------> MainViewController.
In my MainViewController I have the following code.
-(void)addMenuViewControllerWithGesture{
self.view.layer.shadowOpacity = 0.075f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[rsMenuViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
}
}
In My InitViewController (LogIn)
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
MainViewController *controller = segue.destinationViewController;
// setting some values before going to the next view.
controller.id = 0;
controller.name = #"harish";
self.topViewController = controller;
}
By doing this, the MainViewController's viewDidLoad is getting called twice and the below value is always set to null.
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Menu"];
Hope it's clear. I am kind of stuck here and looking for a solution.
Thanks
Okay, I figured it out. After a long, arduous experience, I figured it out. I asked a similar question here: iOS Adding Menu Causes Crash When Not First View and eventually answered it. I just recently came upon your question.
So let's say you have numerous files (.m and .h for each):
InitViewController
MenuViewController
MainViewController
SpeakersView
The objective was to switch from MainViewController using a button not on the slide menu to SpeakersView, but doing it directly caused the slide menu to be null, as was pointed out by Phillip Mills.
Instead, I put this in InitViewController.h, right underneath #Interface:
#property (nonatomic, retain) NSString *location;
Then this under #implementation in InitViewController.m:
#synthesize location;
I originally had this under ViewDidLoad in InitViewController.m:
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Main"];
I changed it to this:
if([location length] == 0){location = #"Main";}
self.topViewController = [self.storyboard instantiateViewControllerWithIdentifier:location];
That way if the variable was empty, it defaulted to #"Main".
Then in MainView.m, where I execute the code after pressing the button, I have this:
InitViewController *ini;
ini = [self.storyboard instantiateViewControllerWithIdentifier:#"Init"];
ini.location = #"Speakers";
And voilĂ , the view switches just fine to Speakers. More accurately, it switches to InitViewController which automatically switches to Speakers or whatever I set location to.
Hopefully this helps you.
Any questions, let me know.
Related
I am using ECSlidingViewController in my app for Facebook style swipe effect. I have 2 TopViewControllers, one left and one right side view controller and one initviewcontroller which is a slidingviewcontroller subclass.
1. InitViewController:ECSlidingViewController
2.MainViewController (TopViewController)
3.LeftMenuViewContrller (UIViewController)
4.RightMenuViewController (UIViewController)
5.DetailViewController (TopViewController)
I have tableview on my MainViewController which contains the calendar events. The problem is that I want to go to MainViewController to DetailViewController by clicking the event in tableView:didSelectRowAtIndexPath: methods to show the events details which is another topview controller with some animation( which I am unable to get so far). I am using following code which is getting me to the DetailViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailsViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"details"];
self.slidingViewController.topViewController = newTopViewController;
[self.slidingViewController resetTopView];
}
this is my viewDidLoad method
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.layer.shadowOpacity = 0.75f;
self.view.layer.shadowRadius = 10.0f;
self.view.layer.shadowColor = [UIColor blackColor].CGColor;
if (![self.slidingViewController.underLeftViewController isKindOfClass:[LeftViewController class]]) {
self.slidingViewController.underLeftViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Left"];
}
if (![self.slidingViewController.underRightViewController isKindOfClass:[RightViewController class]]) {
self.slidingViewController.underRightViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Right"];
}
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
}
I want to get the animation like the UINavigationController or Modal style
[self.navigationController pushViewController:newTopViewController animated:YES];
or
[self presentViewController:newTopViewController animated:YES completion:nil];
please help. thank you.
Are you using Storyboard? Could you perform a Segue? In the storyboard setup the name and the link and style as Modal along with the Transition.
In your DidSelectRowAtIndex put this
[self performSegueWithIdentifier:#"eventDetail" sender:#(indexPath.row)];
Then declare this method
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"eventDetail"])
{
DetailsViewController *destViewController = segue.destinationViewController;
destViewController.eventRow = sender;
}
// You can test for other Segue names here
}
Then in the DetailsViewController.h put
// Allows sending View Controller to give this controller data
#property (nonatomic, strong) int *eventRow;
And in the .m put
#synthesize eventRow;
Now in your DetailsViewController it should animate to it and the sliding will be disabled (unless you declare all the ECS bits as normal). You also have an Int eventRow which tells you which cell was clicked.
You can create a back button and do this;
[self dismissViewControllerAnimated:YES completion:nil];
EDIT
OR you could try this but I am not sure if it will animate plus you need to figure out how to pass stuff, maybe a combination of the two...
UIViewController *newTopViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"eventDetail"];
CGRect frame = self.slidingViewController.topViewController.view.frame;
self.slidingViewController.topViewController = newTopViewController;
self.slidingViewController.topViewController.view.frame = frame;
[self.slidingViewController resetTopView];
I have two view controllers. My first is my menu which contains my highscore and a button which performs a modal segue to my second view controller which is my game. Whenever my player loses the game if he beat his highscore I want it to update on the menu.
Right now, when my player loses the game, I create a UIAlertView with 2 buttons, the first is main menu and the second is restart. Here is my simplified code with my attempting to update my high score via delegation.
#protocol highScoreProtocol <NSObject>
-(void)updateHighScore:(int) score;
#end
#interface ViewController : UIViewController <UIAlertViewDelegate> //i have this delegate implemented because i have a uiialertview
#property (nonatomic) int score;
#property (nonatomic, weak) id <highScoreProtocol> delegateHighScore;
#implementation ViewController
#synthesize score=_score;
#synthesize delegateHighScore=_delegateHighScore;
-(void)lostGame{
[self.delegateHighScore updateHighScore:self.score]; //this is where i try to call the method that should update my high score if necessary but this doesn't actually work
UIAlertView *losingScreen=[[UIAlertView alloc]initWithTitle:#"Game Over" message:[NSString stringWithFormat:#"Your Score Is %d", self.score] delegate:self cancelButtonTitle:#"Main Menu" otherButtonTitles:#"Restart", nil]; //once the user loses the game i have an alert view show giving the option to either restart the game or go to the main menu where the high score is
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
//here i'm segueing back to my main menu because he would have pressed the 'main menu' button [self performSegueWithIdentifier:#"MainMenu" sender:self];
} else if (buttonIndex==1){
//here i just reset my attributes and reset my level because he would have pressed the 'restart button'
}
}
#end
#interface MenuVC : UIViewController <highScoreProtocol>
#property (weak, nonatomic) IBOutlet UILabel *labelHighScore; //the labelhighscore is the highscore number
#end
#implementation MenuVC
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *vc=[[ViewController alloc]init];
vc.delegateHighScore=self;//here is set the delegate as myself which i think i'm supposed to do for some reason
}
-(void)updateHighScore:(int)score{
if (score>[self.labelHighScore.text integerValue]) {
self.labelHighScore.text=[NSString stringWithFormat:#"%d", score];
}
NSLog(#"does this method even run");
// this is the method that updates the highscore which I want to run
// but it doesn't, notice I even made an 'nslog' to see if the method
// even runs but I never ever even got a log out in the debugger,
// so this method never runs.
}
If I just need a little help, or if I'm doing everything completely wrong and going about this task the wrong way, please say.
This doesn't work because this:
ViewController *vc=[[ViewController alloc]init];
vc.delegateHighScore=self;
Instantiates a NEW viewcontroller, that has completely nothing to do with the one you are interacting with.
I assume you are using storyboards so, create an identifier for your viewcontroller (on the interface builder -> select your viewcontroller -> identity inspector tab -> write a name where it says Storyboard ID)
And then add this instead of the previous code:
ViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
vc.delegateHighScore = self;
Edit:
Add this to your button action (but delete the segue from the interface builder AND delete this code from the viewDidLoad)
ViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
vc.delegateHighScore = self;
[self presentModalViewController:vc animated:YES];
Since you create a local variable, vc, in your viewDidLoad method, this is not the same one that you create in the button method where you create your modal segue. That's not the right place to set the delegate. Set yourself to the delegate in that button method using whatever reference you create (or have) to the instance of ViewController that you're segueing to. If you need more information or a code sample, post that button method, so I can see how you are segueing.
After Edit: Then you should implement prepareForSegue:sender: and do this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[(ViewController *)[segue destinationViewController] setDelegate:self];
}
I think I'm following how delegation works, here's the tutorial I followed, but I'm messing up somewhere. I'm expecting my delegate to NSLog but it's not. Can anyone find out what am I missing or doing wrong?
My MainViewController.h:
#interface MainViewController : UITableViewController < AddClassDelegate >
MainViewController.m:
- (void)cancelAddingClass {
NSLog(#"Canceled Yo");
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
/*
When a row is selected, the segue creates the detail view controller as the destination.
Set the detail view controller's detail item to the item associated with the selected row.
*/
if ([[segue identifier] isEqualToString:#"addClassSegue"]) {
UINavigationController *nc = (UINavigationController *)segue.destinationViewController;
AddClassViewController *addClassVC = (AddClassViewController *)[nc.viewControllers objectAtIndex:0];
addClassVC.delegate = self;
}
My modal view controller AddClassViewController.h:
#protocol AddClassDelegate <NSObject>
- (void)cancelAddingClass;
#end
#interface AddClassViewController : UITableViewController
#property (weak, nonatomic) id< AddClassDelegate > delegate;
- (IBAction)cancelButtonPressed:(id)sender;
AddClassViewController.m:
#synthesize delegate;
- (IBAction)cancelButtonPressed:(id)sender {
[self.delegate cancelAddingClass];
}
cancelButtonPressed:
is hooked up to the modal view's Cancel button in Storyboard.
Your code looks fine, which suggests the problem is somewhere we can't see. My guess is here:
AddClassViewController *addClassVC = [segue destinationViewController];
addClassVC.delegate = self;
NSLog(#"segued");
Have you embedded your modal view controller in a navigation controller? If so, destinationViewController gives you the navigation controller, not the AddClassViewController. Check what class addClassVC actually is in the debugger.
If it is a navigation controller, no problem, you just need to get to your actual VC using the .viewControllers property. On several lines to make it simpler to understand:
UINavigationController *nc = (UINavigationController *)segue.destinationViewController;
AddClassViewController *addClassVC = (AddClassViewController *)[nc.viewControllers objectAtIndex:0];
addClassVC.delegate = self;
You can do it in fewer lines but it's a mess of casting and nested brackets, which is harder to debug.
Is it possible your main view controller is being released? That would set the weak reference to nil and the message you send to your delegate would simply be ignored because you'd be messaging nil.
Everything is perfect. I haven't seen any issue. Keep break points everywhere and debug it.
hi everyone i am new to iphone development.
Actually i am trying with some sample app where i have a textField in the Viewcontroller and a Button,when i enter a string in the textfield and press the button it should display the same string in NextView.so can anyone help me out in doing this.
i worked with transition between one view to another view,but i need copy string from Viewcontroller1 to NextView
#ViewController1
-(IBAction)next
{
NextView *Nview = [[NextView alloc]initWithNibName:#"NextView" bundle:nil];
[self.view addSubview:Nview.view];
}
Set an ivar in your NextView called "newString" for example, then pass a string to that ivar form your first controller.
For Example, not tested (and this is one of many ways you can do this):
FirstView
NextView * next = [[NextView alloc] initWithNewString: myTextField.text];
[self.navigationController presentModalViewController: next animated: YES];
NextView
#synthesize newString
-(id)initWithNewString:(NSString*)someString
{
newString = someString;
return self;
}
Then throughout your NextView, just call upon newString wherever you want to get the value of the previous views textField.
-(IBAction)next
{
NextView *Nview = [[NextView alloc]initWithNibName:#"NextView" bundle:nil];
Nview.string_Object=string_to_copy;//declare string_Object in NextView.h
[self.view addSubview:Nview.view];
}
Try this:
In your first view while naviagting:
NextView *nav = [[NextView alloc] init];
nav.textFieldValue = textField.text;
[self.navigationController pushViewController:nav animated:YES];
And in your NextView's .h file create a property:
#property(nonatomic, retain) NSString *textFieldValue;
And in .m file synthesize it like:
#synthesize textFieldValue;
Now you can use textFieldValue in NextView class
P.S: Don't forget to release it :)
As you are a beginner, this will be a good guidance for you to understand the exact flow and it will make you learn how to pass values from one class to another.
Here is an approach (haven't tested, but should work)
Give your textField a tag value like
textField.tag = 1;
and in NextView access it like
UITextField *parentViewTextField = (UITextField*)[self.superview viewWithTag:1]
Sorry for the newbie question. I have a UITabBar in my main window view as well as an array of UINavigationControllers for each Tab. The structure is similar to the iPod app in that the main views can be seen by selecting TabBar items and then the user can drill down further with the NavigationController by pushing views to the stack.
What I would like to be able to do is to do the equivalent of pressing a TabBar button at the bottom from any of the subviews in code (i.e., change the selected property of the TabBar and display launch the first view controller for the tab).
Any help would be greatly appreciated.
Dave
[myTabBarController setSelectedIndex:index]
EDIT: Answering the part 2 question from the comment:
You can define a method in AppDelegate for switching to a different tab.
And you can get hold of appdelegate from anywhere and send a message..
something like:
MyAppDelegate *appDelegate = (MyAppDelegate*) [[UIApplication sharedApplication] delegate];
[appDelegate SwitchToTab:index]
alternatively...
[self.parentViewController.tabBarController setSelectedIndex:3];
I'd like to reply to Prakash, but can't figure out how. Maybe I'm blocked until my score goes up.
Anyhow, I hope this helps someone:
I was doing what Prakash said, and nothing was happening. It's because to get a pointer to my app delegate, I was doing this:
AppDelegate_Phone *appDelegate = [[AppDelegate_Phone alloc] init];
When I should have been doing this:
AppDelegate_Phone *appDelegate = (AppDelegate_Phone *) [[UIApplication sharedApplication] delegate];
Newbie mistake.
For this, You just need to take UITabBar controller -
.h File -
UITabBarController *_pTabBarController;
#property (nonatomic, retain) IBOutlet UITabBarController *_pTabBarController;
.m File -
// synthesize it
#synthesize _pTabBarController;
At initial load
// You can write one function to add tabBar -
// As you have already mentioned you have created an array , if not
_pTabBarController = [[UITabBarController alloc] init];
NSMutableArray *localViewControllersArray = [[NSMutableArray alloc] initWithCapacity:4];
UINavigationController *theNavigationController;
_pController = [[Controller alloc] initStart];
_pController.tabBarItem.tag = 1;
_pController.title = #"Baranches";
theNavigationController = [[UINavigationController alloc] initWithRootViewController:_pController];
theNavigationController.tabBarItem.tag = 1;
theNavigationController.tabBarItem.image = [UIImage imageNamed:#"icon_branches.png"];
[localViewControllersArray addObject:theNavigationController];
[theNavigationController release];
than you can set index as per your needs
self._pTabBarController.selectedIndex = 0; // as per your requirements
[self.parentViewController.tabBarController setSelectedIndex:3];
Selected the index for me but it just highlighted the navbarcontroller's index as the active index, but while it highlighted that index it was actually on a different viewcontroller than was suggested by the tabbarmenu item.
Just wanted to add that I used this from my view controller, and it performed like someone actually pressed the menuitem; from code:
UITabBarController *MyTabController = (UITabBarController *)((AppDelegate*) [[UIApplication sharedApplication] delegate]).window.rootViewController;
[MyTabController setSelectedIndex:1];
Thank you for this post/answers it helped out a lot in my project.
I wanted to do something similar but for XCode 6.4 iOS (8.4) setSelectedIndex by itself won't do it.
Add the view controllers of the tab bar to a list and then use something like the following in some function and then call it:
FirstViewController *firstVC = [[self viewControllers] objectAtIndex:0];
[self.selectedViewController.view removeFromSuperview]
[self.view insertSubview:firstVC.view belowSubview:self.tabBar];
[self.tabBar setSelectedItem:self.firstTabBarItem];
self.selectedViewController = firstVC;
You might have similar code already inside your didSelectedItem..
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
if (item == self.firstTabBarItem)
// Right here
}
else if ...
}