How do I pass a NSDate using storyboard properly? - ios5

I want to pass a NSDate from PickDateController to DetailViewController
so on PickDateController I have an IBAction as follows:
-(IBAction)doneDate:(id)sender{
NSLog(#"Date Here DPC = %#", [datePicker.date description]); //This shows fine
dateLabel.text = [datePicker.date description]; //This also shows.
DetailViewController *controller = [[[DetailViewController alloc] init] autorelease];
NSDate *dateSel = datePicker.date;
[controller setDateSelected:dateSel]; //This DOES NOT go to DetailViewController
controller.dateSelected = dateSel; //This doesn't work either
[self.navigationController popViewControllerAnimated:YES];
}
For a dummy like me what am I missing ?
How should I write the -(void)setDateSelected{} on DetailViewController ? Or is it not the issue ?

Considering that there are existing segues between the controllers and DetailViewController did a segue to PickDateController:
If you use alloc/init, you wont get the controller instantiated by the storyboard. If you have a segue between those, you don't need to create a new controller but rather implement prepareForSegue in your view controller to create a "back channel" (in order to pass the information back you cannot create a new segue back (they only go "in", never "back"):
You need to create a sort of PickDateControllerDelegate and a delegate property on your PickDateController. You then can set the delegate to your calling DetailViewController, in the prepareForSegue method of your DetailViewController.
You now can access it via self.delegate from within your PickDateController and thus report any information back before being dismissed / poped form the navigation stack. The delegate can and should also be used to inform the calling controller that it may dismiss the PickDateController (instead of dismissing itself).
Beginning Storyboards, part 2 is a good reference on doing this (you can use assign and retain properties for weak and strong if you're not using ARC yet.

Related

passing a string value from one view controller to a second variable view controller Xcode

I have an app in which I am loading variable view controllers depending on where the user is in the app. This is my code.
-(IBAction)buttonPressed:(id)sender;{
if (mission <1) {
gameViewController *detailViewController = [[gameViewController alloc] initWithNibName:#"gameViewController" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController.which2 = which;
}
else if (mission > 0) {
NSString *viewController = #"gameViewController";
NSString *missionViewController = [viewController stringByAppendingString:missionNo];
Class controllerClass = NSClassFromString (missionViewController);
id detailViewController = [[controllerClass alloc] initWithNibName:#"gameViewController" bundle:nil];
NSLog(#"missionViewController;%#",missionViewController);
[self.navigationController pushViewController:detailViewController animated:YES];
detailViewController .which2 = which;
}
}
everything work great except I want to pass a string from the first view controller to the second view controller which ever one that may be.
As you can see I have put in the code just above detailViewController.which2 = which;
I have created the property and synthesized NSString *which in my first view controller and NSString *which2 in all the subsequent view controllers. in the first instance where mission is <1 everything works ok and NSLog shows the string being passed. However with the second detailViewController (which is the variable view controller) I get the error Property 'which2' not found on object of type"_strong id' Does anyone have any suggestion on how to resolve this?
the other viewControllers are gameViewController1, gameViewController2, etc. Each is rather long and complex. But they all load into the same xib file gameViewController. There is a UIlabel that update to one higher once the user finishes that gameView so they can go on the the next on in the series or go back to the main menu. If they go back to the main menu the number is added to "gameViewController" so the correct one is loaded. So I can't specify which view controller is going to load since it depends on the user's place. Thus the missionViewController with the # of mission added to load the correct view controller. Each of the subsequent view controllers has a which2 created and synthesized. What if we pretend that all subsequent view controllers just had a UILabel that is going to display the string "which2 in it. All I want to do is pass the string "which" to the next viewController (whichever one that is) as "which2".
Dynamic binding allows you to send messages to an id as long as the selector exists in the project, but dot-syntax is not allowed.
Changing
detailViewController.which2 = which;
to
[detailViewController setWhich2:which];
should suppress the warning.
write this : `detailViewController .which2 = which;
just before you push navigation controller.`
UPDATE:
Use Protools to update the value.
#protocol MissionProtocol
#required
-(void) updateValue:(NSSTring*) value;
#end
Implement the protocols in your ViewControllers. i.e.
#interface MissionViewController:UIViewController<MissionProtocol>
....
#end
In your implementation file, implement the method updateValue.
-(void) updateValue:(NSString*) value
{
self.which2=value;
}
Then change your original code to:
NSString *viewController = #"gameViewController";
NSString *missionViewController = [viewController stringByAppendingString:missionNo];
Class controllerClass = NSClassFromString (missionViewController);
id<MissionProtocol> detailViewController = [[controllerClass alloc] initWithNibName:#"gameViewController" bundle:nil];
[detailViewController updateValue:which];

Memory management, addSubview for a subclass of UIViewController

I have a view that shows a map. I have a custom subclass of UIViewController (DetailViewController) that gets shown when the detailDisclosureButton of the callout above the pin is pressed. While in my map class, I create my detailview and add it to the subview like this:
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailView.locationPoint = locationPoint;
detailView.locationCoordinate = locationCoordinate;
[self.view addSubview:detailView.view];
[detailView release];
My DetailViewController has a TableView and parses the data in DetailViewController. However I get an error of sending the numberOfSectionsInTable message to a dealloc'd instance. I'm assuming it is this since I originally had this as a property and it worked fine with (nonatomic, retain). I'm assuming that I'm releasing it before the next view is done with it. If that is the case, when would I clean up the memory??? It seems like this would be the place to do it. Thanks.
I am not sure what makes you adding the view of DetailViewController into this mapviewcontroller's view. Don't you think right approach would be to either presentModalViewController or pushNavigationController?
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailView.locationPoint = locationPoint;
detailView.locationCoordinate = locationCoordinate;
//[self.view addSubview:detailView.view];
[self.navigationController pushViewController:detailView animated:YES];
//OR
[self presentModalViewController:detailView animated:YES];
[detailView release];
You are getting the error because you are only using the view and deallocating the view controller immediately and hence tableview datasource and delegates are hitting a nil object.
Views do not retain their view controllers. Someone needs to retain the VC or else it will get released, and then the app will crash when the view makes a call into its delegate. When you use a navigation controller, the navcon has a stack of view controllers that it retains. Likewise with presentModalViewController, the OS takes care of retaining the detail VC.
Adding a detail view as a subview is not the normal way to navigate to a new view. Instead, one either uses a navigation controller and [navcon pushViewController::], or a modal subview and [self presentModalViewController::]. If the detail view occupies only a portion of the parent view, then it is normal to retain the view controller for the subview within the parent controller. That is, within the parent VC (your map class) add a property for the detail VC. Actually, it's more common to not even use a VC for a subview, but rather for screen-filling detail views.

problem in displaying a string in a textbox

Hi to all,
I passed a variable from first.m to seViewController.m. I'm able to print that variable using NSLog(#variable) but I'm unable to use textField.text=variable. How to print that variable in a textbox?
First.m
-(void)buttonPressed01
{
seViewController *seView = [[seViewController alloc] init];
[seView insert:myString];
[self.navigationController popViewControllerAnimated:YES];
}
seviewcontroller.m
-(void)insert:(NSString*) myString
{
NSLog(#"%#",myString);
textField.text=[NSString stringWithFormat:#"%#",myString];
}
seViewController *seView = [[[seViewController alloc] initWithNibName:#"seViewController" bundle:nil] autorelease];
[seView insert:String];
[[self navigationController] pushViewController:seView animated:YES];
seviewcontroller.m
-(void)insert:(NSString*) myString
{
NSLog(#"%#",myString);
textField.text=myString;
}
Until your seViewController is loaded you can not use its outlets, here you are using textField. It won't set text because after seViewController *seView = [[seViewController alloc] init]; the view is initialized but still you need to load its view in memory in order to use its outlet. so if you are using its view then after addingSubview, or presenting modalView or, pushing it on navigation stack call that method.
or else you should have a string in seviewcontroller which you will set and when controller's will be loaded in memory viewDidLoad just do what you are doing right now in insert method, set TextField's text.
Also, I am not sure what you want to do with seView? why you are creating new instance and not using it ? May be you have created this controller earlier and you want to change that controller's textField text not the new one. Then in that case you should refer that controller not this one because its totally different object.
Thanks
When you pop from stack it loads the instance of the view controller you pushed in to stack. Here you created a new instance and set the text field and loads the instance in the stack. Thats why text field does not show the value to set. If you want to pass the value to the class you nee to pass the value using some singleton class or app delegate.
I think its not working because you are passing this variable to a new instance of your seViewController while you are popping it in the next line. You have to get the same instance as -
seViewController *seView = (seViewController*)[self parentViewController];
[seView insert:myString];
[self.navigationController popViewControllerAnimated:YES];
You can use this one if what I understood is correct,
you can retrieve the array of viewControllers from the navigation controller.
You dont need to initialize the view controller and this wont work as explained above.

A couple of problems customizing Apples MultipleDetailViews Example

I have been trying to add/implement this example to my existing Split View app tests.
Apple Example
I what to use the concept of replacing the detail view or right view, otherwise my app will be different. It is this difference that is causing my problems.
I have a rootviewcontroller or left view and upon choosing something here a new view is pushed onto this view. Upon choosing something in this "pushed view" I want to change the detail view or right hand view. This is the difference to apples example where the rootview does not have a pushed view on it and thus references are not broken.
Below is my change code - the new View DVCases is being initialized but the didload is not happening.
The issues are learner issues to do with my classes.
This below code is in my RootViewController implementation code but my reference to splitviewcontroller is not working if there is a new view pushed.
Second self.navigationcontroller is not correct because I have pushed a second view to the rootviewcontroller.
To centralize and simplify the code what I have done is from the delegate of the pushed view in the didselect event i call a method found in the rootviewcontroller passing the index as a parameter. The code for my custom method contains what is below.
So my question is how do I do this in my situation where I have pushed other views onto the rootview or left side. It appears that after pushing a view the reference to splitviewcontroller is gone and self.navigationcontroller is also gone/or wrong.
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (value == 0) {
DVCases *newDetailViewController = [[DVCases alloc] initWithNibName:#"DVCases" bundle:nil];
detailViewController = newDetailViewController;
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
I would appreciate any tips or help you might have.
Initialization of any viewcontroller class does not mean that it will make call to viewDidLoad method.
viewDidLoad method will only be called when you load view of that viewController. Generally we do it either by following methods.
1. Pushing it on navigation stack.
2. Presenting it using modal transition.
3. Adding it on some other view using [someView addSubView:controller.view];
4. Selecting any tabBar item for the first time Or tapping tabBar Item twice.
there may be some other scenarios.
But right now in your code I don't see any of this element.
Initialization means you are calling the direct method for intialization(calling its constructor) like here in above code initWithNibName will call this method of DVClass not any other(until this method had call for other methods inside it).
Thanks
As I am learning to properly code - my problems centres around that.
The above code is perfect as long as you call it using the same instance. I was not. Thus it was not working.
In the end I made my RootViewController a delegate for a method that has the above code. Thus when in another view - this view can call this method and the proper or real instance of RootViewController will implement it.

How do I pass an object into a delegate?

I am creating a delegate view controller and presenting it to the user to perform an action but I would like to change a NSString on the delegate view controller based on the originating view controller. For example if the delegate view controller is a delegate of viewControllerA, then display Foo, but if its a delegate of viewControllerB then display Blah. ALthough I cant figure out how to pass some sort of information that indicates what the originating view controller is. I noticed that if i do an NSLog(#"I'm from %#",[self delegate]); it will tell me what the originating view controller is, as well as the memory address, but I cant seem to translate that into an NSString object to examine its value. If theres a way to make that work, or a better way to do this then that works too...
- (IBAction)editDate {
DatePickerViewController *datePickerView = [[DatePickerViewController alloc] init];
datePickerView.delegate = self;
datePickerView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:datePickerView animated:YES];
[datePickerView release];
}
It seems like you're using some terminology in ways that are different from what most Objective-C coders would mean.
Here you're instantiating a view controller to show as a modal view. That view controller has a property called delegate that allows it to call some methods to report changes to its state. That doesn't make it a "delegate view controller", that makes it "an object with a delegate".
You happen to be using another view controller class as the delegate, but any object that implements the methods that DatePickerViewController objects want to call to report changes could be assigned to that delegate property.
I think that the question you're asking is "how do I make the DatePickerViewController display different information depending on what kind of object it's reporting to?", and the answer is much the same as "how do I make a UILabel show different text depending on the view controller that created it?"—you set properties or call methods on in when you create it.
If you really just want to pass a string to DatePickerViewController, you could add an NSString* property to DatePickerViewController and set it with arbitrary text, with
datePickerView.myString = #"some information that you want";
You could use the class of the delegate.
if([[self delegate] isKindOfClass:[ViewControllerA class]]) {
[self doViewControllerAThings];
}
else {
...
}