So essentially I'm inserting "startViewController" into "mainViewController" now of course I can access startViewControllers methods from mainViewController but I was wondering how to do the opposite? Occasionally startViewController will need to call something in mainViewController and I was just wondering how I do this?
Thanks in advance.
Add an ivar of your mainViewController to your startViewController and set this when showing the view.
Or you can design a nice clean protocol, and make one view the delegate of the other.
Related
I've recently started developing for the iPhone and so far I'm doing pretty good but there's this basic pattern I really don't seem to get.
Say, I have a TabBar with two views and a custom delegate protocol, thus my structure is the following:
AppDelegate.h/.m
myDelegateProtocol.h
FirstViewController.h/.m
SecondViewController.h/.m
MainView.xib
FirstView.xib
SecondView.xib
Now I want to achieve the following: I placed a button in the FirstView.xib and I'd like the IBAction which it invokes (inside FirstViewController ofc.) to send a message to the SecondViewController ([self.delegate tellSecondViewContrToSayHi]) and invoke another method which simply prints a log into the console saying "hi I'm here."
So far I know what I need to do in theory:
Specify the protocol.
Implement the protocol in the SecondViewController.
Create an id< myDelegateProtocol > delegate inside my FirstViewController,...AND last but not least:
Set the self.delegate = secondViewControllerObject.
Now, nr.4 is where the problem's at. How on earth do I link the delegate to the other viewController? I mean I'm not the one instantiating the views as the tabBar kinda does that for me,... any advise? Or am I just way too tired to notice a really stupid thing I did somewhere?
Theoretically the same question also applies to the target:action: thing,... I mean, how do I define the target?
Thanks a lot,
wasabi
You have the right idea, assuming that you want relatively tight coupling between these controllers via that delegate protocol.
Since neither controller knows about the other until that delegate property is set you need to have some object which has a reference to both of them wire up that relationship. In your case that's probably the application delegate which can create both controllers, set one as the delegate of the other, and pass both along to your tab bar controller.
What you might actually want is to have the app delegate give both controllers a reference to some shared model object. Your FirstViewController can update that model when you tap a button and your SecondViewController can observe changes to the model to update it's display (or just update its view when it appears based on the current model state). That way your controllers don't need to know anything about each other.
I am new to ios development and I am trying to use some methods in different view controllers in regular intervals of time (using same methods in different view controllers).
Can anyone please tell me what is the best method for this?
Thanks in advance!
I'd suggest using protocol for this. You can never know when you want different method behaviour for different controllers. And you can always implement default behaviour in private category of generic uiviewcontroller.
Maybe you could try to implement this method in a customViewController that would be subclassed by these viewController and than every viewController would have access to these method.
Alternate way would be to implement it on the appDelegate or on a common tabBarController, navigationController (or whatever) and so every viewController would have access to it.
If the time interval has to be the same for every viewControler, you should do only one time interval and iterate on your viewControllers
In my iPhone project I have a UIViewController in which I add an instance of a subclass of UIView. From this instance I need to communicate back an integer to my view controller. My current solution is to send a message from my instance to my App Delegate which sends a message to the view controller. It works, but it feels a bit messy.
Is there anyway I can send a message straight back to the view controller?
I would love to be able to do something like [super doSomething:123];
Any ideas?
Thanks
This is the kind of thing that NSNotificationCenter was provided for. Once you get handy with sending and receiving notifications, your message-passing gets a WHOLE lot simpler.
One of the classic things people confront is how to get a pointer to the object they want, in order to tell it about something. How do I, for instance, tell the ViewController two slots back up the UINavigationController stack that the user just changed this data field? So you dig into the stack, offset back by some magic number of elements in the stack, build public setters on the fields you want talk to... It's super cumbersome.
Compared to registering as a notification receiver in one place, and then firing a notification in some complete other place when the data changes. It's kind of magical, after doing all the "dig through the view hierarchy" work.
Um, I'm not sure I understand your problem correctly. You have a class derived from UIView which needs to send a message to another class derived from a UIViewController. It sounds like you are creating the UIView instance programmatically. Is there any reason my you could not have a property on the UIView which refers to the UIVIewController and just use that to send it a message directly.
You cannot use [super ...] because the super of your UIView derived class would be UIView.
Or am I miss-understanding the issue :-)
If I understand correctly, you want to send a message from your subclass of UIView to the view controller.
That means your subclass of UIView needs to have a property or ivar which is the view controller. The easiest way to do this is to add it as an outlet and connect it to the view controller in the nib file.
Generally you should not go via the app delegate. Having a typed pointer link is also less than ideal.
The optimal way of communicating - Apple does it like this as well - is to create a delegate protocol. When creating the view controller you pass a pointer to the delegate as id . Then when it gets to sending the message you ask the delegate:
if ([delegate respondsToSelector(didFinishSomething:)])
{
[delegate didFinishSomething:info_to_pass];
}
If you want to be extra-sophisticated then you can also add a pointer to the calling class instance. Like:
[delegate myViewController:self didFinishSomething:info_to_pass];
This way you always know what kind of class the message is coming from.
If there is more than one place that needs to be notified of a change, then instead of delegation you will use notifications.
In my iPhone project I have a
UIViewController in which I add an
instance of a subclass of UIView.
This implies that you have both a reference to the instance of the UIView subclass and the UIViewController in the same scope. I.e. something equivalent to:
UIViewControllerSubclass *myViewController;
UIViewSubclass *myView;
(It doesn't matter if they are actually instance variables or, even, globals)
And once those two variables are initialized, somewhere you do something like:
myViewController.view = myView;
In your UIViewSubclass, add a property that points back to your UIViewControllerSubclass:
#property(assign) UIViewControllerSubclass *myController;
Then, when you do the above assignment, add:
myView.myController = myViewController;
From there, messaging your controller from your view is easy:
[self.myController yoManHereIsAnInt: 42];
Note that I used assign instead of retain because the controller already retains the view. If the view were to also retain the controller, you would have a cycle that would eventually lead to a leak.
No super about it. super is entirely related to the inheritance hierarchy of your Objective-C classes. What you are asking has nothing to do with inheritance and everything to do with how the various instances of objects in your application are connected together.
Simply add an outlet to your UIView subclass, connect it to its view controller in Interface Builder, and call your method on that. Here’s how that might look:
MyUIView.h:
#interface MyUIView : UIView
{
UIViewController *viewController;
}
#property (assign) IBOutlet UIViewController *viewController;
#end
MyUIView.m:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[[self viewController] setTitle:#"Hello from MyUIView"];
}
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.
The iphone program is set up in the Utility Application model where you have a root view and two subviews (mainViewController & flipsideViewController) which are outlets.
If I try to set the UISwitch at rootViewController's viewDidLoad (with [flipsideViewController.switchInstance setOn:YES]), it doesn't work.
Within flipsideViewController, that method works but not outside of it. Any idea why? I can pass other methods...
Even if I pass a method to the flipsideViewController that then does the setOn method, it still doesn't work...
Any ideas?
Just as a 'sanity-check' (as others have put it to me) have you made sure your flipsideViewController variable is not null at the time you are calling the above code?