I have an image in my RootViewController (which is selected from a UIImagePickerController), which I need to pass to a new view through a navigation controller. I have the following code that I use to pass strings to the next view:
//Get strings
NSString *text1 = line1.text;
NSString *text2 = line2.text;
NSString *text3 = line3.text;
NSString *text4 = line4.text;
//Create an GeneratedViewController and initialise it with given data
GeneratedViewController *gController = [[GeneratedViewController alloc] initWithNibName:#"GeneratedViewController" bundle:[NSBundle mainBundle]];
gController.text1 = text1;
gController.text2 = text2;
gController.text3 = text3;
gController.text4 = text4;
[self.navigationController pushViewController:gController animated:YES];
[gController release];
gController = nil;
How might I pass an image to the GeneratedViewController?
Thanks,
Jack
The easiest solution would be to create a property of type UIImage on GeneratedViewController.
Then after creating and initializing the GeneratedViewController but before pushing it onto the navigationController you will need to set the image property on the gController to the selected image.
A property on the controller, just like the text is set
In a method, or the initializer
through a notification (NSNotificationCenter). This is a bit more advanced.
Through delegation, where the first controller is a datasource delegate on the Generated Controller. This allows the second controller to get what it needs, whenever it wants.
Which method to use depends on how the controllers are created, when the image can change, and how many different pieces of data the second controller needs - one or two bits, properties work fine. More than that, I tend to use delegation.
Related
Rookie question: I am writing a program that will generate a specific string and then display it in a text window in a different view controller. I have been testing to ensure that the code in fact generates the string using NSLog commands and I know the code is working as intended. For some reason it is not transferring across the view controller and I cant figure out why. Any help? Here is a snippet of the code:
CreateStoryViewController.m
- (IBAction)makeStory:(id)sender
{
StoryLine *myStory =[[StoryLine alloc] init];
[myStory setStory];
self.story = myStory.plot;
NSLog(#"story is %#", self.story);//this is generating the correct story string
self.displayStoryController = [[BIDDisplayStoryViewController alloc] initWithNibName:#"DisplayStoryView" bundle:nil];
[self.view insertSubview:self.displayStoryController.view atIndex:1];
}
DisplayStoryViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
BIDCreateStoryViewController *newStory = [[BIDCreateStoryViewController alloc] init];
NSLog(#"newStory.story is %#",newStory.story);//this generates null message
self.storyDisplay.text = newStory.story;
}
This is wrong. You're instantiating a new BIDCreateViewController object inside your second view controller. This is not the same as the original BIDCreateViewController object that pushed your second BIDDisplayStoryViewController.
You need to declare a string property in your BIDDisplayStoryViewController's header file.
Something like
#property (nonatomic, retain /*or strong, if using ARC*/) NSString *storyToDisplay;
Be sure to synthesize this in your implementation file as well.
When you create BIDDisplayStoryViewController inside your first view controller, you need to do it as follows:
self.displayStoryController = [[BIDDisplayStoryViewController alloc] initWithNibName:#"DisplayStoryView" bundle:nil];
self.displayStoryViewController.storyToDisplay = self.story;
Now inside your second view controller you can access this using self.myStory.
While this will solve your problem (and please do understand that it's not my intention to be rude here), I feel that there's a lack of understanding of how iOS (and OOP in general) works.
In your viewDidLoad method you are making a whole new story. This story is totally different from the one you made in the makeStory: method. You should add a StoryLine Property to DisplayStoryViewController.h, and set that after you init your displayStoryController.
make the intended variable a property type at .h file, so the other file can access it
I have two controllers A & B
In B there are one label and one string
In A i have write the below code
B *ObjB =[[B alloc]initWithNibName:#"B" bundle:nil];
ObjB.Mylabel.text=[NSString stringWithString:#"Add New name"];
ObjB.MyString=[NSString stringWithString:#"new string name"];
[self.navigationController pushViewController:ObjB animated:YES];
[ObjB release];
I am only getting the ObjB.MyString value in B , not getting the label text.Can any one help.Thanks in advance.
Well assuming that MyLabel is a UILabel (sidenote: avoid capitalized names for ivars - in Objc capitalized names are used [by convention] for Classes), the reason that the value is not set is because the view hierarchy of your B controller has not yet been loaded (ie your label is nil at this point). So you got three options:
Force the view hierarchy to load & then set your label:
[ObjB loadView]; // Note: Apple says that you never should call this directly (just to illustrate my point)!!
Let the system load the hierarchy for you by requesting the view first:
id view = ObjB.view; // This is a bit of a 'hack' actually
Just add another property in your B controller, set that and on viewDidLoad set your label's text (This is the best option in my opinion)
The best way to pass data between two view controllers is to declare a variable in controller B, to hold the labels text.
In viewController B's header file
NSString *labelText;
//Declare its property and synthesize in .m
In controller A, before navigating to controller B, initialize this variable to the text you want, i.e. in this case "Add New Name".
B *ObjB =[[B alloc]initWithNibName:#"B" bundle:nil];
ObjB.labelText = [NSString stringWithString:#"Add New name"];
ObjB.MyString = [NSString stringWithString:#"new string name"];
[self.navigationController pushViewController:ObjB animated:YES];
Next in the viewDidLoad of controller B, assign the label's text to the variable which contains the string.
ViewDidLoad of B
MyLabel.Text = labelText;
//Assuming you have mapped MyLabel to the IB.
Also i use ARC for all my projects, so I dont use the release command.
This solved my problem
B *ObjB =[[B alloc]initWithNibName:#"B" bundle:nil];
[self.navigationController pushViewController:ObjB animated:YES];
ObjB.Mylabel.text=[NSString stringWithString:#"Add New name"];
ObjB.MyString=[NSString stringWithString:#"new string name"];
[ObjB release];
Thanks for your immediate response
i don't know if anyone is using this open source library for replacing UIPopovercontroller for an iPhone.
i'm trying to deploy the FPPopover into my project, everything is working like i want, but the problem is that i'm not able to return any value to my ViewController.
i'm trying this in didSelectRowAtIndexPath
myParentViewController *parentController =(myParentViewController*)self.parentViewController;
but the problem is that self.parentViewController is (null)
i have also another problem, how can i dismiss the FPPopoverController from within didSelectRowAtIndexPath.
I dismissed the view by adding a popoverView property to the table view controller that is popping up (in this case ATableViewController), and then assigning the FPPopoverViewController to that property. Like this:
ATableViewController *aTableViewController = [[ATableViewController alloc] init];
FPPopoverController *aPopoverController = [[FPPopoverController alloc] initWithViewController:aTableViewController];
aPopoverController.delegate = aTableViewController;
aTableViewController.popoverView = aPopoverController;
Then in didSelectRowAtIndexPath of aTableViewController you can just call:
[self.popoverView dismissPopoverAnimated:YES];
If you are trying to return values to the "parent"...since the parentViewController property is null here, you can just make your own property for it (let's call it "parentView"). So when setting up the above you would use:
aTableViewController.parentView = self;
Then you can access any of the properties of the parentView and return values from the aTableViewController that popped up. A bit of a workaround, but that's what I did...hope it helps!
I'm trying to make a modal view which displays the champion of my app.
there's a NSMutableString variable called champ in modal view,
which is supposed to be updated by returnChamp function in main view.
the champ string is correctly set in main view,
but in modal view, the champ value appears as (null).
In fact, it seems it doesn't even go into the returnChamp function.
so apparently something wrong with my calling or implementing returnChamp,
but I have another function that does the similar, and that works fine.
could anyone please help me?
-(void) mainView{
.....
champ = [[currentPlayers objectAtIndex:playerIndex] retain];
NSLog(#"%#",champ);
modalWinner = [[winner alloc] init];
modalWinner.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:modalWinner animated:YES];
}
- (NSMutableString *) returnChamp{
NSLog(#"returnChamp");
return champ;
}
//in modalWinner
-(void) modalView{
..............
champName = [[NSMutableString alloc] init];
NSLog(#"%#", [(MainViewController *)self.parentViewController returnChamp]);
champName = [(MainViewController *)self.parentViewController returnChamp];
UIImage *champImage = [UIImage imageNamed:champName];
}
self.parentViewController is probably not actually a reference to your object. For some reason, it seems that the framework always insists on setting a UINavigationController as self.parentViewController - even for modals, and to the extent that it will create one if there isn't already one. This is probably going unnoticed because you're casting it to your MainViewController type.
You'll need to find a different way of making your original object available to be communicated with, or perhaps pass the appropriate value to the newly-instantiated controller before you present it.
For example, if you add a champName property to the modal class, you can do:
modalWinner = [[ModalWinnerViewController alloc] init];
modalWinner.champName = myValue; /* Set value before presenting controller */
[self presentModalViewController:modalWinner animated:YES];
There will probably be some code needed to update the UI with this value. The viewWillAppear method of the modal view controller is a good place for this as it is called by the framework immediately before the view is presented.
Note that this property-based approach could be used to keep a reference to your intended parent object, as well. And see here for a different approach to solving a similar problem.
I've got a problem that I think is probably straight forward but I can't seem to wrap my head around it.
I've got a tableview that loads from an array of NSDictionaries. Each Dictionary has a title (shown in the row) and an associated nssstring representing a viewcontroller that should be pushed onto the stack when the row is selected. In other words, selecting row "A" needs to initialize an instance of "aViewController" and push it on the stack, selecting row "B" needs to initialize an instance of "bViewController" and push it on the stack, etc.
I originally just hardcoded all possible values into didSelectRow. But I'd really like to be able to dynamically generate the viewController dynamically. I found a few C++ examples of similar problems that led me to the code below. But I can't seem to get it right and am not sure I'm on the right track for an objective-c solution. Anyone have any thoughts?
Here's the didSelectRow code that's not working:
Class cls = [selectedRow valueForKey:#"viewController"];
if (cls!= nil)
{
id myNewController = [[cls alloc] init];
}
[[self navigationController] pushViewController:myNewController animated:YES];
[myController release];
Are you storing the actual Class or the class name (as an NSString) in the dictionary?
If the value you are storing in the dictionary is an NSString I don't think you can just assign Class cls = someNSString;
You can, however, do:
NSString *controllerClassName = [selectedRow valueForKey:#"viewController"];
if (controllerClassName != nil) {
id myNewController = [[NSClassFromString(controllerClassName) alloc] init];
[[self navigationController] pushViewController:myNewController animated:YES];
[myNewController release];
}
OR
Just store the Class in the dictionary instead of the NSString representation: