How change PickerView delegate from one controller to another one? - objective-c

With the storyboard I've built one ViewController1 with an "Add" button. Click on add display a PopoverView (in ViewController2) with only a Picker within.
So my PickerView's delegate is in ViewController 2 but I want it in ViewController1...
Is there a easy way to do this so ?
Thanks

In your ViewController1 prepareForSegue method, try this:
if ([segue.identifier isEqualToString:#"MySegue"])
{
ViewController2* vc2 = segue.destinationViewController;
vc2.pickerView.delegate = self;
}
It basically assigns the delegate of the pickerview to ViewController1 before the segue is finished being called.
This of course is assuming your pickerview is setup as a property.

In your ViewController1.h file, change your interface header to this;
#interface ViewController1 : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>;
That makes your ViewController1 in charge of the delegates. Then add the methods you want in the ViewController1.m file. Also, set the delegate of the UIPickerView to your instance of ViewController1 with this:
[yourPickerview setDelegate:ViewController1];

Related

Multiple webviews in one UIViewController

Lets say I have a UIViewController with two buttons, both going (push) to another UIViewController that has two UIWebViews (showing two different PDF files), how can I make sure that only the one I choose via the button is showed?
You need to pass some information to the UIViewController which has the UIWebViews, saying which button was pressed. Then, based on that information, decide which of the UIWebViews to display.
As you are using storyboards, I suggest you look into prepareForSegue. It will allow you to set a property on the destination view controller with something like the following. You should add this to the UIViewController which contains the buttons.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"buttonOne"]) {
ExampleViewController *destViewController = segue.destinationViewController;
destViewController.buttonClicked = #"One";
} else if ([segue.identifier isEqualToString:#"buttonTwo"]) {
ExampleViewController *destViewController = segue.destinationViewController;
destViewController.buttonClicked = #"Two";
}
}
You can then use the buttonClicked property in the destination view controller to decide which you should display. If you have two separate UIWebViews, you could choose to hide one using webViewOne.hidden = YES; and show the other using webViewTwo.hidden = NO;.
However, it would probably be neater to only have a single UIWebView. You could then use prepareForSeque to pass in the URL of the PDF you would like it to display, rather than just sending the name of the button clicked.
Assuming you webView is in a view controller called SecondViewController and your buttons are in the view controller called FirstViewController
1) Create an object in your SecondViewController.h
#interface SecondViewController : UIViewController
#property (nonatomic, strong) NSString *whichButtonClicked;
#end
2) Import SecondViewController in your FirstViewController
#import "SecondViewController.h"
3) In you button IBAction method in FirstViewController.m . use this code
- (IBAction) firstButtonClicked
{
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"secondView"];
secondViewController. whichButtonClicked = #"first"
[self.navigationController pushViewController:secondViewController animated:YES];
}
- (IBAction) secondButtonClicked
{
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"secondView"];
secondViewController. whichButtonClicked = #"second"
[self.navigationController pushViewController:secondViewController animated:YES];
}
PS Don't forget. In you Storyboard. Set Storyboard ID for SecondViewController as secondView
4) In your SecondViewController.m use this code to check which button
if ([self.whichButtonClicked isEqualToString:#"first"])
{
///display first web view here
}
else
{
//display second web view here
}
Hope this helps

How to set properties of an object, for which Xcode is unaware exist, but do

Edit - I've revised to clarify.
//myViewController.h
#property (strong, nonatomic) SCDataObject *dataObject;
In storyboard, I've created a single VC with the custom class myViewController. I've given it the storyboard ID myViewControllerStoryboardId.
//anotherClass.m
UIViewController *viewController =
[self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
I instantiate the custom VC, but notice I'm setting it to a pointer of type UIViewController on purpose for a few reasons.
//anotherClass.m
//I want to set the property, dataObject, of the instantiated VC, but this doesn't work.
viewController.dataObject = something;
The actual object has the property, but the pointer to it is of a different class. How do I set the property?
You need to use your viewcontrollers class. I used MyViewController, just replace it with your class name. Here is the code:
#import "MyViewController.h"
...
MyViewController *viewController =
[self.storyboard
instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
//It works!
viewController.dataObject = something;
EDIT:
If you really don't want to use your custom class, give this code a shot:
[viewController setValue:something forKey:#"dataObject"];
But i can't think of a reason for doing this.
if myViewController is a subclass of UIViewController then you should really do:
myViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
You also need to make sure that you change the class of your custom UIViewController in your Storyboard from the generic UIViewController to myViewController (select your VC in the StoryBoard and then go to the "Identity Inspector", that is the 3rd tab, in the right-hand Utilities screen. You can change there the class of the custom VC to your subclass).
Update after Question Edit:
The UIViewController class is part of UIKit. Anytime you need to customize a VC beyond what can be done in SB, you need to subclass UIViewController (and create a custom VC). So if you are trying to have a custom property (dataObject) of a UIVC without subclassing UIVC, the answer is you can't.
Having said that, maybe the question is not fully clear. If you are looking to have a subclass of UIVC with a property dataObject but with multiple instances of that subclass; you can always create that subclass once and then have multiple instances of that class that you would give different names so:
myViewController* viewController1 = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
myViewController* viewController2 = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
myViewController* viewController3 = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
They will all be different instances of the same subclass (myViewController) and the values of the dataObject will be distinct for each instance. In other words, you can set:
viewController1.dataObject=someObject;
viewController2.dataObject=anotherObject;
If you just type viewController as id, though you still can't use the property directly, you could send it a message the corresponds to that property, without warnings. You could use respondsToSelector: to see if it supports the accessor function for that property.
id viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
if( [viewController respondsToSelector:#selector(setDataObject:)] ) {
[viewController setDataObject:something];
}
Personally, I would probably just:
MyViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewControllerStoryboardId"];
viewController.dataObject = something;
You will get warnings, but this should work for setting:
[viewController setDataObject:something];
And this for getting:
[viewController dataObject];
To avoid a crash, you probably would do something like this:
if ([viewController respondsToSelector:#selector(setDataObject:)])
{
[viewController setDataObject:something];
}

How to modify the sender ViewController from the called ViewController?

I have a login view controller called from a Storyboard segue. When the user logs in correctly, I need to close the current ViewController, return to the caller ViewController and hide the login button.
How can I refer to the sender ViewController, to hide the button? Do I have to pass an instance of the root ViewController to the login or is there another way?
Use delegation.
For your DetaliViewControler create a protocol, like
#protocol DetailViewControllerDelegate <NSObject>
-(void)successFullyLoggedInOnController:(DetailViewController *) controller;
#end
add a delegate declaration to DetailViewController's interface like
#property (weak) id<DetailViewControllerDelegate> delegate;
Make the MasterViewController conform to the protocol.
-(void)successFullyLoggedInOnController:(DetailViewController *) controller
{
[self.loginButton setHidden:YES];
}
Now just before the MasterViewController displays the DetailViewController, doe something like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"DetailViewSegue"]) {
DetailViewController *vc = segue.destinationViewController;
vc.delegate = self;
}
}
In the DetailViewController once the credential where entered and verified call
[self.delegate successFullyLoggedInOnController:self];
and dismiss the DetailViewController
You should use delegation. Make the VC with the button the other one's delegate. When log in is successful, you dismiss your VC and call the delegate method to hide the button.

Calling method to view controller delegate, won't dismiss modal view

I have the following simple view controller class set up
#protocol ThermoFluidsSelectorViewControllerDelegate;
#interface ThermoFluidsSelectorViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) id <ThermoFluidsSelectorViewControllerDelegate> delegate;
// user hits done button
- (IBAction)done:(id)sender;
#end
#protocol ThermoFluidsSelectorViewControllerDelegate <NSObject>
-(void) didFinishSelection:(ThermoFluidsSelectorViewController *)controller fluidID: (NSString *)fluidID;
#end
the 'didFinishSeletion: fluidID:' method is defined in the master view controller and should dismiss the selector view controller when called. When the done button is pressed the following method is called:
- (IBAction)done:(id)sender
{
[[self delegate] didFinishSelection:self fluidID:nil];
}
the 'done:' method gets called (checked with an alert) but 'didFinishSelection...' is not getting called so the view will not revert back to the main screen. Any ideas?
It sounds like you have not assigned your delegate in your master view controller.
You should have something like this in your master view controller which sets up the delegate:
ThermoFluidsSelectorViewController *view = [[ThermoFluidsSelectorViewController alloc] init];
view.delegate = self;
here you can see I create the view, then set the delegate of the view back to myself.
If you are not creating the Thermo... view controller programatically, but have used a storyboard, then you can set the delegate in the prepareForSegue: method of your master view controller:
// Do some customisation of our new view when a table item has been selected
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure we're referring to the correct segue
if ([[segue identifier] isEqualToString:#"MySegueID"]) {
// Get reference to the destination view controller
ThermoFluidsSelectorViewController *cont = [segue destinationViewController];
// set the delegate
cont.delegate = self;
Hope this helps.

ViewControllers Navigation

I have one base view controller "contentViewController" with one button
the action on button is
(IBAction) goBack:(id)sender
.h file
#interface ContentView : UIViewController {
}
#property(nonatomic,retain) UIViewController *display;
-(IBAction) goBack:(id) sender;
.m file
#synthesize display;
-(IBAction) goBack:(id)sender{
UIViewController *view= display;
[display release];
[self presentModalViewController:view animated:YES];
}
and there are some other view controllers already exist each view controller contain on button to show content on the contentViewController.. here is one class example:
.h file
#interface Info : UIViewController {
}
-(IBAction) viewHealthInfoContent:(id) sender;
.m file
-(IBAction) viewHealthInfoContent:(id)sender{
ContentView *cv=[ContentView alloc];
[cv setDisplay:self];
[self presentModalViewController:cv animated:YES];
[cv release];
}
the case is, each time i show content from one view controller i need to go back to it. using that one goBack button on the contentViewController but when i click the go back button it doesn't do any think !!! any help
When you want to go back your previous viewController, use dismissModalViewControllerAnimated:: method.
According source :
Dismisses the modal view controller that was presented by the receiver.
In iOS, you can display views modally by presenting the controller for the modal view from your current view controller. When you present a view modally using the presentModalViewController:animated: method, the view controller animates the appearance of the view using the technique you specify. (You can specify the desired technique by setting the modalTransitionStyle property.) At the same time, the method creates a parent-child relationship between the current view controller and the modal view controller.
Source