Calling function in the first view from the other viewcontroller - iphone

I hope that you will succeed in at least a little to clarify me how and what to do, I'm sure I'm wrong, so I really need an expert opinion.
I have two viewcontroller together with nibs what I want is to call function that is in first class from another ViewController, the problem is that another viewcontroller manages to call this function but the only thing I can see that is done is NSlog which outputs in the console (which I put in that position to know that the function is called)
example:
FirstViewController.m
-(void)drawingFunction:(NSString*)inputText{
NSLog("Feature was launched");
/* showing stuff in FirstView.xib */
}
SecondViewController.m
-(void)turnOnFunction:(id)sender{
FirstViewController *stuff= [[PrviViewController alloc] init];
[stuff drawingFunction:#"ShowAll"];
}
Basically when I call that function in the PrviViewController.m meaning without reference to the outside e.g.
[self drawingFunction:#"ShowAll"];
everything is well displayed, but when I try to call this function from SecondViewController.m all I see is just a "feature was launched" on the console
I really don't know what to do ...

if i get you right, the FirstViewController is on top of the view controller hierarchy (either within a navigation controller or presented modal)? So, if that is the case just creating an instance of SecondViewController and calling a function which should change the user interface on the view which corresponds to SecondViewController will do nothing at all.
You have to present the SecondViewController and its view with presentModalViewController:animated: for instance. After that the view of SecondViewController will be shown and you can do any changes on that view. Also calling the method drawingFunction: will act as you expect it.
Cheers,
Andreas

You're confusing instances with classes. You don't send messages (call functions) to classes, you send them to instances.
In this case, you have two entirely separate instances of FirstViewController. The first is created by loading the nib and the second is created in -[SecondController turnOnFunction:]. The drawingFunction: message is being sent to the second instance when you want it to be sent to the first.
You need to link the nib instance of FirstViewController to the SecondController instance. You can do that with an outlet in interface builder or you can assign it when you create the display the SecondController.

Related

Is there a way to avoid viewDidLoad beeing called after every segue?

i initialize tables, data etc in my main ViewController. For more settings, i want to call another Viewcontroller with:
DateChangeController *theController = [self.storyboard instantiateViewControllerWithIdentifier:#"dateChangeController"];
[self presentViewController:theController animated:YES completion:^{NSLog(#"View controller presented.");}];
And some clicks later i return with a segue (custom:)
NSLog(#"Scroll to Ticket");
[self.sourceViewController presentModalViewController:self.destinationViewController animated:YES];
My Problem:
After returning to my main ViewController, viewDidLoad is called (everytime).I read, that the ARC releasing my mainView after "going" to the other ViewController and calling the viewDidUnload Method, but i want to keep all my data and tables i initialize at the beginning..
Any solution? Thank you very much!
The problem is that you are doing this:
main view controller ->
date change controller ->
a *different* main view controller
In other words, although in your verbal description you use the words "returning to my main ViewController", you are not in fact returning; you are moving forward to yet another instance of this main view controller every time, piling up all these view controllers on top of one another.
The way to return to an existing view controller is not to make a segue but to return! The return from presentViewController is dismissViewController. You do not use a segue for that; you just call dismissViewController. (Okay, in iOS 6 you can in fact use a segue, but it is a very special and rather complicated kind of segue called an Unwind or Exit segue.)
If you do that, you'll be back at your old view controller, which was sitting there all along waiting for your return, and viewDidLoad will not be called.
So, this was a good question for you to ask, because the double call of viewDidLoad was a sign to you that your architecture was all wrong.
I think you're taking the wrong approach - viewDidLoad is supposed to be called when it is called - it's a notification to you that the view is being refreshed or initially loaded. What you want to do is move that table initialization code somewhere else, or, at least, set a Boolean variable so that it is only called once. Would it work to create an object that has your table data when viewDidLoad is first called, then to check it to see if it's already been called?

passing data back to a previously allocated UIViewController

I have a view controller that then has a button that passes to an option menu.
When options are set they need to be past back to the previously allocated viewcontroller.
How is this possible without 'alloc and init another' instance of the object?
You can achieve this by using a delegate protocol. First view controller should become the delegate of the second view controller and then you can call this delegate method in your first view controller once the selection is done.
You can lookup google for implementation of delegates in objective-c. Its pretty simple. Add a
#protocol <delegatename>
<declare delegate method>
#end
Create a member variable in the second view controller for assigning the delegate. And define the method in the class implementing the delegate.
When you init your option viewController, pass it a reference to its parent.
I.E.
[[OptionViewController alloc] initWith...: parent:];
Use a #property or a method or somesuch to call on the parent to pass the data back.
You could use a shared singleton?
http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
Or save the parameters to nsuserdefaults and read them back in in your first viewcontroller
or some other temporary store such as your appdelegate
I've used all three of the above approaches before.

Get current view instance?

I have a class: MainViewController
An instance of that controller is controlling the current view.
I have another class: DetailClass in which I have an instance of MainViewController, myMainViewController.
How can I set myMainViewContoller equal to the instance of MainViewController currently controlling the view seen by the user?
I think you're confusing "instance" and "pointer to instance." Your question would make much more sense if you said that DetailClass has an instance variable that's a pointer to an instance of MainViewController. I'll assume that's what you meant.
Usually in these situations, one of the controllers has created the other one, or some other object has created both of them. The first case is common in navigation-based apps, while the second is likely if the two controllers are managed by a tab bar controller. Either way, there's generally some object that knows about both controllers. So, let's say that your MainViewController creates an instance of DetailClass. If that's the case, it can simply pass a pointer to itself as part of the initialization, or perhaps after the DetailClass instance has been created. Does DetailClass have a -setMyMainViewController: method? If yes, MainViewController might have some code that looks like this:
//...
DetailClass *detailController = [[DetailClass alloc] initWithNibName:nil bundle:nil];
[detailController setMyMainViewController:self];
//...

Accessing a instance method within another view controller

I have a tab bar controller with 4 tabs. Each tab has its own view controller and a UIWebView.
Let's say I have a button (button1) in vc1 and an instance method onClick1 as well. In vc2 I have a method named reload. My question is, how do I access the specific instance method, onClick1 in vc2, from vc1?
For further detail, I'm actually trying to code a simple shopping utility for the iPhone. When a user adds an item to the cart from the browse view, I want to be able to automatically reload the cart view.
Below are some examples of what I mean. This problem has been more difficult than I thought. I'm not sure if I have redesign my application or what. Perhaps have both vc1 and vc2 belong to a subclass of vcmain and have reference to each of them there? However, if I do that, then how do I refer them to their corresponding .xib? Thanks guys!
#implementation viewController 1
//Reloads vc2
-(IBAction) onClick1: (id) sender {
//Calls vc2 reload
[vc2 reload];
}
#end
#implementation viewController 2
//Reload View
-(void)reload {
[webView reload];
}
#end
You've basically got three approaches, each one of which has plusses and minuses. I'm going to give you a high-level overview and let you go to Apple's quite comprehensive documentation for details. Hopefully I can give you the right terms to google for more specific help.
The approach that #dredful quite ably details is to have a handle to the "other" view controller(s) and call methods on them directly. That works fine, but it can be confusing and cumbersome handing pointers to all your controllers around, and traversing the view hierarchy to get get at the controller you want can be very tricky indeed.
The second approach is Key-Value Observing. You can register one view controller to "watch" a particular key (named property) of another view controller, and fire a particular selector when various things happen with it. This is kind of magical and nice, although at some point you have to have pointers to both controllers at the same time, which doesn't entirely relieve the downside of the "call it directly" method above. It is also a sort of unfortunate coupling of view control and data, kind of breaks MVC.
The third approach is using NSNotificationCenter. A class can post a notification, and any other object that registers itself to listen for that sort of notification can be triggered when that happens. It's nice because you might have LOTS of different objects adding items to the cart, and they can just shoot the notification center a note (even passing it an object or arbitrary data, if it wants), and the cart view can consume those notifications, catch the passed objects, and do its thing, not caring in particular who's talking to it. It keeps separate pieces of your application nicely decoupled. The downside is, it's got a bit of overhead to it, and whatever selector the notification-consuming class performs happens synchronously, so you can't hide network activity or some other long process there.
I'm thinking you should already have something like a base UIViewController (let's call it MyTabBars) that has a UITabBarController *tabBarController containing all your Tab Bar View Controllers. If that sounds familiar, you will want a method in MyTabBars called -(void)reloadCart. reloadCart will walk the array of tabBarController.viewControllers. On each viewController you can perform a respondsToSelector:#selector(reload) and if the specific viewController qualifies then it calls that selector method.
In order to do this you probably want all your vc1, vc2, ... files to have an id delegate defined and synthesized. When MyTabBars creates the different tab bars it sets the vc1 and vc2 delegate to self.
#implementation MyTabBars
//Reload Cart View
-(void)reloadCart {
for (UIViewController *thisUIViewController in tabBarController.viewControllers){
if ([thisUIViewController respondsToSelector:#selector(reload)]) {
[thisUIViewController reload];
}
}
}
#end
Assuming you know how to pass a delegate of MyTabBars into your vc1 and vc2, then you can now have the following code in vc1:
#implementation viewController1
//Reloads vc2
-(IBAction) onClick1: (id) sender {
//Calls MyTabBars reloadCart which will look for all tab bar view controllers
//that have the 'reload' method
[delegate reloadCart];
}
#end
This solution idea will cause MyTabBars to trigger any reload method found in any of our tab bar view controllers. Therefore be careful with the naming of such a method in your vc1, vc2, etc files. This solution will trigger a unique vc method or multiple vcs with the same method depending on your naming convention.
Hope this helps.

Passing info to a delegate from a UIActionSheet

My understanding about passing data back to a delegate completely revolves around making a new view controller and having it conform to a protocol.
I am trying to get a time input back from a UIDatePicker set with the UIDatePickerModeCountDownTimer mode and I am running into issues.
Inside of Main1.m I create a UIActionSheet *action, and set everything up so that it presents itself with a UIDatePicker on a click. Inside of Main.m I also say:
main.delegate = self;
If this were not a UIActionSheet, I would make a protocol reference inside the new ViewController and then have the new vc pass data to a method that Main has, but I can't do that with a UIActionSheet!!
What am I missing? I assume there is something inherently different about Action Sheets, ut I can't figure it out.
Thanks for your help!!!
EDIT:
Sorry! I was giving a generic name to my view controller. It isn't actually Main.m, its FirstViewController.h/m
I didn't realize that my generic reference was getting mixed up with the Main.m file that is completely different than a vc.
I don't exactly understand why you're putting your delegate assignment in Main.m. I assume that you're setting up your UIActionSheet in a ViewController, and launching it from there. In this case, your ViewController is your delegate object. So you need to make sure that your ViewController implements the UIActionSheetDelegate. ie:
#interface SomeController : UIViewController <UIActionSheetDelegate>
Then you simply implement the required methods of that delegate in your view controller class, and that should do it. If I'm missing something about how you're implementing this, then you need to provide more code examples to examine.