I accidentally assigned the same custom class to two UIViewControllers in Storyboard:
#interface SecondViewController : UIViewController
With this the app ran properly. But when I change the custom class for the second View Controller from FirstViewController to SecondViewController the app crashes when the second View Controller loads. How do I rectify this situation?
More information is definitely needed here. However, one of the things to look for is that if you are using the FirstViewController class in code somewhere (in -prepareForSegue for the presenting UIViewController for instance), you'll need to make sure to change that code so that it's using the proper pointer for the class when referencing the SecondViewController class.
For instance, if you do the following and the destinationViewController is of class SecondViewController, then you will get a crash:
FirstViewController *firstView = (FirstViewController *)[segue destinationViewController];
If you could post the presenting class and the FirstViewController and SecondViewController classes, then we can provide more information.
This is embarrassingly obvious now, but I found the problem arose from a button being linked to an IBAction in the the FirstViewController class. When the app was run it crashed because of the improper link.
Related
I know this has been asked, but I can't figure out how to make this work with my app -- I'm sure I'm doing it wrong.
I have two view controllers embedded inside a UITabBarViewContoller, FirstViewController and SecondViewController. SecondViewController is nothing more then a few UITextFields for managing a hostname and port that the app connects to.
FirstViewController contains most of the code (which I know isn't very MVC oriented). I'm trying to implement Delegation from SecondViewController back to FirstViewController (Passing Data between View Controllers) but it seems like my delegate methods aren't being called. Since this is based on storyboards, I'm not creating the instance of SecondViewController and I'm not sure how to set the Delegate. Is there a way to access the instance of SecondViewController so I can set the Delegate?
milesper thank you!
My solution (in swift)
let secondView = self.tabBarController.viewControllers[1] as SecondViewController
secondView.delegate = self
I have problem with calling methods from one UIViewController by another UIViewController.
Currently I have UIScroll view with two UIViewControllers.
I want to change something in second one and see results in first one.
I try to do this in this way:
Inside function of second UIViewController:
-(void)doSomething:(){
FirsOneViewController *firstVC = [FirsOneViewController alloc] init];
[firstVC changeUnits:0];
}
Function is called but I don't se any changes in first controller.
BR,
Paul
From your code I see you create a new instance of FirstViewController and so there is no reason why the current instance inside the scrollview would receive this message.
You need to send the changeUnits: message to the current FirstViewController, so you need a reference to it. To do this you may want to think about creating a protocol, so that you parent container (the scrollview) is notified by the SecondViewController and then notifies the FirstViewController. A simpler(and lazier) solution is make the SecondViewController have a strong reference to the FirstViewController (though this solution may bite you in the future).
As said in other answers you are creating a new instance of FirsOneViewController instead of referencing to the one you already have.
Here are three ways of doing what you are asking:
Delegation:
The FirstViewController should be the delegate of the SecondViewController (as the secondViewController is calling methods on the FirstViewController). You should tell the SecondViewController that the FirstViewController is its delegate in what ever class initialises the two viewControllers.
From what you have said so far this seems like your best option.
NSNotification:
This could be good option if you think more than one object will want to listen to the change in the SecondViewController. Just post an NSNotification in the SecondViewController and add an NSNotification listener in the FirstViewController
Singleton:
if there should only ever be one instance of the FirstViewController in existence then make it a singleton. By making a class initialiser method. so that you can create/get the current instance of the object from anywhere in your appellation.
Hope this helped.
I have two questions about this one. First, I have the navigation controller successfully put in the storyboard and is linked with the tabs and is working how I would want it to. Except for one thing. When I try to add a code such as this
[self.navigationController popToViewController:vc animated:YES]
I get an error Property 'navigationController' not found on object of type 'AppDelegate *'
Is this because I put it in the wrong place? Or becasue its a tabbar application and something aint right.
It sounds like you're trying to make a call to your navigation controller from your AppDelegate. Unless you've specifically setup your AppDelegate to work with your navigation controller (it'd need to be a subclass of UIViewController), you'll get an error because there is no Navigation Controller on your AppDelegate class (by default). Therefore, when you make that call - the navigation controller can't be found. Notice how your AppDelegate is a subclass of UIResponder, not UIViewController:
#interface AppDelegate : UIResponder <UIApplicationDelegate>
Instead, create and / or connect your navigation controller to a UIViewController subclass - then you can make calls like this from your subclass:
[self.navigationController popToViewController:vc animated:YES];
To create and setup a Navigation Controller, follow these steps (may vary if you aren't using storyboards).
Create a new UINavigationController Obj-C subclass. In the Xcode menu bar, select File > New, or press CMD+N. Name your class and set its superclass as UINavigationController:
Note that you don't absolutely need an entirely new class! You can use an existing class that is a subclass of UIViewController - as long as the navigationController property is available.
Add your navigation controller from the objects library in Xcode and set it up the way you need it.
Select the NavigationController in your Storyboard, then open the Utilities Panel, and select the Identity Inspector Tab. Set the Custom Class name to the name of your UIViewController or UINavigationController subclass:
From your class you'll be able to use the navigationController property, among hundreds of others relating to the View Controller. Remember that the AppDelegate is really a place for setting up your app and handling app events (ex. app closing, app backgrounding, app opening).
I may go mad very soon.
This is the reason:
- I started up with Single View Application project with storyboards. Then I set the view controller class name in the storyboard for my viewController.
- Next step I created one pointer for this viewController in AppDelegate method ...didFinishLaunchingWithOpt... and filled it up by calling [myStoryboards instantiate...]. It works pretty good because I can call method like [vc1 setMyName] which does smthng like self.myName = #"Johnny";
- But here it comes. When I create IBAction method joined with button, this method doesn't know anything about "Johhny". And this is because I'm in another instance. When I check the address of "self" it is another one...
WhyWhyWhy??? Please help, how can I use still the same object - the one instantiated in AppDelegate by storyboards and the one from storyboards in "interface builder".
Thank you.
Oh my. I think I really underestamated it...
When we were talking about getting pointer of other viewControllers from storyboard...
I have initialViewController got by calling rootViewContr... And another one connected with segue (modal) where is UITableView. A get data on rootViewController and I want to show them on the other one in the list (UITableView). So I call segue (performSegueWithIdentifier), the other controller is shown but the list is clear. Because the method I call is working with tableView variable which is null :/ Because, again, I'm in another object. That is because I call that method storyboard instantiate... How can I get exactly the same viewController which I'm working in storyboard with. It is quite confusing for me :/
I read something about prepareForSegue and getting the pointer by destinationViewController but that is not what exactly I want. I need the pointer before I call segue method and the viewController is shown...
Thank you.
If you've set up your initial view controller properly in the storyboard, you don't need to assign it to the windows rootViewController property in -applicationDidFinishLaunchingWithOptions: as this is done for you automatically. It sounds like you're creating a second instance. To access the original instance setup by the storyboard simply do this in -applicationDidFinishLaunchingWithOptions:
InitialViewController *viewController = (InitialViewController *)self.window.rootViewController;
viewController.myName = #"Johnny";
I have a UIViewController (MyViewController) and another view controller i'm presenting modally though MyViewController (call it SecondViewController). I want to be able to send a message to MyViewController from SecondViewController by using
[self.parentViewController hideSecondViewController];
But since parentViewController is defined as a UIViewController, and hideSecondViewController isn't a method of UIViewController, I get a warning saying "UIViewController may not respond to 'hideSecondViewController'". It works fine, because it CAN send the message successfully during the program, but since I #import SecondViewController in MyViewController, I can't #import MyViewController in SecondViewController. Any way around this?
When it comes time to dismiss a modal
view controller, the preferred
approach is to let the parent view
controller do the dismissing. In other
words, the same view controller that
presented the modal view controller
should also take responsibility for
dismissing it whenever possible.
Although there are several techniques
for notifying a parent view controller
that it should dismiss its modally
presented child, the preferred
technique is delegation.
In a delegate-based model, the view
controller being presented modally
must define a protocol for its
delegate to implement. The protocol
defines methods that are called by the
modal view controller in response to
specific actions, such as taps in a
Done button. The delegate is then
responsible for implementing these
methods and providing an appropriate
response. In the case of a parent view
controller acting as a delegate for
its modal child, the response would
include dismissing the child view
controller when appropriate.
Read more at the View Controller Programming Guide for iOS.
P.S:
since I #import SecondViewController
in MyViewController, I can't #import
MyViewController in
SecondViewController.
To solve a circular dependency problem you can use a forward declaration.
It would be better to redesign your architecture as albertamg proposed but this should work:
[self
dismissModalViewControllerAnimated:YES];
you can call dismiss on both the presenting and presented view controller and it will do the same thing.