How can I pass data from parent to child view? - ios

I have a container view, which uses a storyboard embed segue to load an embedded static table view. The segue ID is 'CONTAINER'.
When I run the following code, the prepareForSegue never actually gets called so no data is passed from the parent to the child.
- (void)viewDidLoad {
[super viewDidLoad];
if ([sGender isEqualToString:#"MALE"]) {
containerGender = #"MALE";
if ([containerGender isEqualToString:#"MALE"]){
NSLog(#"MALE");
}else{
NSLog(#"BROKEN");
}
}
else if ([sGender isEqualToString:#"FEMALE"]) {
containerGender = #"FEMALE";
}
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"CONTAINER"]) {
if([containerGender isEqualToString:#"MALE"]) {
if ([containerGender isEqualToString:#"MALE"]){
NSLog(#"MALE");
}else{
NSLog(#"BROKEN");
}
SportTableViewController *tableView = segue.destinationViewController;
tableView.sportGender = #"MALE";
}
else if ([containerGender isEqualToString:#"FEMALE"]){
SportTableViewController *tableView = segue.destinationViewController;
tableView.sportGender = #"FEMALE";
}
}
}
My question is:
a)Why is prepareForSegue not called? Does the Storyboard Embed Segue behave differently to a standard seque?
b)Is there a better way of passing data from the container view to the embedded table?
Also please ignore the messy implementation/various log tests, just my attempts to work out whats going wrong.

My question actually stems from a misunderstanding of how container views load their embedded views. Apparently, it all happens before viewDidLoad. That means my conversion of sGender into containerGender took place too late.
I fixed it by passing sGender to the embedded view directly. I had thought I'd already tried this, but yesterday was obviously a slow day ;).

you can do it..
try
in childViewController
set-
#property(nonatomic,retain)parentViewController *parent;
and
in ParentViewController set-
ChildViewController *child = [[childviewController alloc]init];
child.parent=self;
It will set your parent class in childview and you can get data through parent object in child view controller.

Related

passing nesting through segue nil on init methods but valid on viewdidload

I have made a segue passing a string which tells the next view controller which instance to parse the CoreData for. The problem is, I am using some code that calls init methods and the sent string is not initialized when it is called. However, the segue is working when I display the string in the destination view controller's viewDidLoad
- (id)init
{
self = [super init];
if (self)
{
[self initFakeData];
}
return self;
}
When that initFakeData method is called it sets up a graph and needs the exercise to hold a valid value
- (void)initFakeData
{
NSString *myExercise=exercise; //returns nil
if (myExercise==nil)
{
myExercise=#"Default";
}
}
Meanwhile...
-(void)viewDidLoad{
NSString *myExercise=exercise; //returns value
}
exercise is a property that is initialized by the previous view controller in a tableview
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([segue.identifier isEqualToString:#"showGraph"]) {
JBLineChartViewController *destViewController = segue.destinationViewController;
NSString *myExericse=[NSString stringWithFormat:#"%#", [[_exercises valueForKey:#"exercise"]objectAtIndex:indexPath.row]];
NSLog(#"%#",myExericse);
destViewController.exercise = myExericse;
}
}
The behaviour is correct because during init the exercise in JBLineChartViewController was not set. If you need the exercise attribute in the init method to set certain behaviour that have to be before viewDidLoad, my suggestion is to not use segue but do a designated initWithExercise and push the controller in code. Maybe like this:
- (IBAction)chartButtonPressed:(id)sender {
JBLineChartViewController *vc = [[ShopViewController alloc]initWithExercise:#"EXERCISE_STRING_HERE"];
[self showViewController:vc sender:self];
}
The new view controller is allocated and initialized before prepareForSegue is called. Anything you need to do with CoreData should be done in viewDidLoad. Or you can do it later, e.g. in viewWillAppear or viewDidAppear.

Passing Data between view Controller and a Table View Controller

I am trying to pass a string value namely,'_passedDataDate' from a viewController to a TableView Controller. And there in the TableViewController,I am trying to keep it in a array namely,'_dateArray'. while trying to do so, at first a nil object gets inserted and then the real object. how to avoid this nil value getting added?
Here is the code bellow,
- (void)viewDidLoad {
[super viewDidLoad];
_dateArray = [[NSMutableArray alloc] init];
_dateString = _passedDataDate;
if(_dateString){
[_dateArray addObject:_passedDataDate];
NSLog(#"Added Passed Data");
NSLog(#"%ld",[_dateArray count]);
}
else{
NSLog(#"No object Added");
NSLog(#"%ld",[_dateArray count]);
}
}
Output is as follow:
No object Added
0
Added Passed Data
1
Why No object Added is getting printed? I do not want it what shall Ido about it?
Also,I get the below warning,
Warning: Attempt to present on whose view is not in the window hierarchy!
Don't use Segue inside the button action.
Hide the segue
[self performSegueWithIdentifier:#"pass" sender:nil];
And try this :
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString: #"pass"])
{
TableViewController *tableView = [segue destinationViewController];
tableView.passedDataDate = #"HAI";tableView.passedDataDestination = #"Hellio";
}
}

UIView inheritance for multiple UIView in iOS

I'm trying to build a simple iOS app that will simply roll dice with a different number of sides (d20, d12, etc...)
I'd like to create a view that I will re-use multiple times in the same UIViewController, as seen here: http://cl.ly/image/2s30353F3V1K (the only thing that changes is the # of sides)
What I can't figure out is how to properly create the UI element in the storyboard without simply copying and pasting the ContainerView's embeded object for each different number of sides.
Is there an easy way to sub class this properly? I'm new to iOS storyboards and was trying to use OO principles.
So you have a DieViewController, but you need the different instances to have different number of sides.
#interface DieViewController
…
#property (nonatomic) NSInteger numberOfSides;
…
#end
The question is how to communicate the proper number of sides to each contained instance. This is where the embed segue comes in. In the storyboard, set the storyboard embed segue identifier to something unique (I'll use 6SidedDie). Finally, in ViewController add a -prepareForSegue:sender:
##implementation ViewController
…
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"6SidedDie"]) {
DieViewController *dieViewController = segue.destinationViewController;
dieViewController.numberOfSides = 6;
}
}
…
#end
of course, you can mix this up to allow for lots of dice. Here is code which could handle the identifiers 6SidedDie and 10SidedDie.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier hasSuffix:#"Die"]) {
DieViewController *dieViewController = segue.destinationViewController;
if ([segue.identifier hasPrefix:#"6Sided"]) {
dieViewController.numberOfSides = 6;
} else if ([segue.identifier hasPrefix:#"10Sided"]) {
dieViewController.numberOfSides = 10;
}
}
}
UPDATE
You can use the self.viewControllers array to access the content in the DieViewController instances.
DieViewController *dieViewController = self.viewControllers[0]; // The first die view controller
if (dieViewController.numberOfSides == 6) {
// This is the six sided die.
}
NOTE: self.viewControllers will not be ordered. You will need to check numberOfSides to see which type of die this is.
I don't understand your question clearly but I have an idea
First, you get an instant of UIViewController
YourViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"Identifier"];
[vc methodToChangeTheSideProperty:(NSString *)side];
CGRect frame = vc.view.frame;
//change frame of the view as you want
...
...
vc.view.frame = frame;
Then, add the view of your controller to container you want to show it
[yourViewContainer addSubview:vc.view];

Pass informaion back to mother view

I'd like to pass some object from one view (number 2) to view number 1. View 1 triggers view 2 and before that in "prepareForSeque" I'm passing "self" to the second view and store it in variable "delegate". After some time I'd like to pass back new created object to view 1 and I'm trying to achieve it but I got an error that method is not visible for this interface. How to pass created object to the mother view triggering method?
When I declare #property someObject and synthetize it, it works ok using delegate. Is there another option or am I forced to use delegate?
Code:
- (IBAction)saveAndClose:(id)sender {
KwejkModel *mod = [[KwejkModel alloc] init];
((ViewController *)self.delegate).model = mod;
}
It works ok, but is there another option triggering method not using the property? Like this:
[((ViewController *)self.delegate) someMethod];
but here is an error.
Here is my code:
VIEW 1
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"addItemSeque"]) {
ScrollViewViewController *destViewController = segue.destinationViewController;
destViewController.delegate = self;
}
}
-(void) addNewPosition:(KwejkModel *)newKwejk
{
//for testing only this
[modelArray count];
}
VIEW 2:
- (IBAction)saveAndClose:(id)sender {
KwejkModel *mod = [[KwejkModel alloc] init];
// ((ViewController *)self.delegate).model = mod;
//it crashes here with error:-[NSPlaceholderString initWithString:]: nil argument' but it sees method from VIEW 1
[self.delegate addNewPosition:mod];
}
Try this link: Passing Data between View Controllers
Take a look at the first answer under Passing Data Back.

Thread1 exc_bad_access (code =2)... help me

i've been fixing this problem for a few days. but can't seem to get it..
help me out ..
let me explain my situation. Basically, i have navigation controller that contains table view controller and view controller. and i'm making simple phone book app.
And, i have a directory entry declared in extension class
#interface DetailViewController ()
#property DirectoryEntry *dirEntry;
#end
And, in table view, when you click the button it will transfer some data through segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DetailViewController *detailCV = [segue destinationViewController];
if ([segue.identifier isEqualToString:#"cellToDetail"]) {
[detailCV setDirEntry: [self.pbArray objectAtIndex:[self.tableView indexPathForSelectedRow].row]];
} else {
detailCV.dirEntry = nil;
}
//designate delegate !!!
detailCV.delegate = self;
}
My Problem occurs when it execute detailCV.dirEntry = nil; it will call my setter in viewController. it says EXC_BAD_ACCESS
-(void) setDirEntry:(DirectoryEntry *) dirEntry {
self.dirEntry = dirEntry;
}
Thank you in advance..
It's not an EXC_BAD_ACCESS so much as the OS killing your app for smashing the stack. This method is recursing infinitely:
-(void) setDirEntry:(DirectoryEntry *) dirEntry {
self.dirEntry = dirEntry;
}
Your use of dot notation expands to a setter which should make this more clear.
-(void) setDirEntry:(DirectoryEntry *) dirEntry {
[self setDirEntry:dirEntry];
}
Set the instance variable directly, or let the compiler handle it. Properties in class extensions are automatically synthesized.

Resources