moving indexPath.row to a label using addTarget: action: forControlEvents: - ios

I am trying to move my indexPath.row to a different viewcontroller - pageView label. This is what I have tried:
[cell.nav addTarget:self action:#selector(naviguate:) forControlEvents:UIControlEventTouchUpInside];
cell.nav.tag=indexPath.row;
-(void)naviguate:(id)sender {
UIButton *theButton=(UIButton *)sender;
NSLog(names[theButton.tag]);
pageView *secondViewController = [[pageView alloc] initWithNibName:#"secondViewController" bundle:nil];
secondViewController.name.text = names[theButton.tag];
}
Why is this not changing the label text on pageView. How should I do it?
Where the Logs string works fine.
Edit for #danh
I have tried this:
-(void)naviguate:(id)sender {
[UIView animateWithDuration:0.5
delay:0
options: UIViewAnimationOptionCurveEaseOut
animations:^{
[_tableView setFrame:CGRectMake(0, 569, _tableView.frame.size.width, _tableView.frame.size.height)];
}
completion:^(BOOL finished){
[self performSegueWithIdentifier:#"link" sender:self];
}];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
UIButton *theButton=(UIButton *)sender;
if([segue.identifier isEqualToString:#"link"])
{
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
pageView *controller = (pageView *)navController.topViewController;
controller.name.text= names[theButton.tag];
}
}
where it is being called by
[cell.nav addTarget:self action:#selector(naviguate:) forControlEvents:UIControlEventTouchUpInside];
cell.nav.tag=indexPath.row;
But I am getting the error [pageView topViewController]: unrecognized selector sent to instance ... Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[pageView topViewController]: unrecognized selector sent to instance
Do you know why?
2nd attempt
with:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
UIButton *theButton=(UIButton *)sender;
if([segue.identifier isEqualToString:#"link"])
{
pageView *controller = (pageView *)segue.destinationViewController;
controller.name.text= names[theButton.tag];
}
}
I get the error '-[ImagesTableViewController tag]: unrecognized selector sent to instance
WHich is crashing because of names[theButton.tag] How come?

This line:
pageView *secondViewController = [[pageView alloc] initWithNibName:#"secondViewController" bundle:nil];
creates a new view controller, then this line:
secondViewController.name.text = names[theButton.tag];
sets one of it's view's properties (which is wrong, because the view isn't loaded yet, and because it's ill-advised to mess around with another vc's views). But that doesn't really matter, because this line:
}
destroys the newly allocated vc, which will never be heard from again.
The way to fix is either to use a segue from the starting view controller, and set properties of the destination in prepareForSegue:, or to push or present the secondViewController. Either:
// if we're in a navigation controller
[self.navigationController pushViewController:secondViewController animated:true];
// or, if there's no container
[self presentViewController:secondViewController animated:true completion:nil];
Remember, no matter how you decide to present secondViewController, don't try to set the state of one of it's subviews directly. Instead, give it a property like NSString *theStringMyLabelShouldShow, and set that from the presenting vc. The second VC can mess with it's own views in viewWillAppear:
self.name.text = self.theStringMyLabelShouldShow;

Related

How to get the parentViewController in childViewController?

I have a main UIViewController and named AddInformationController. In this mainViewController I have two UIContainerView. Each of them embed with a UITableViewController. The table view controllers are named InformationSegmentController and ResultSegmentController.
I put this in AddInformationController:
InformationSegmentController *isc = [self.storyboard instantiateViewControllerWithIdentfier:#"InformationSegmentController"];
ResultSegmentController *rsc = [self.storyboard instantiateViewControllerWithIdentifier: #"ResultSegmentController"];
[self addChildViewController: isc];
[self addChildViewController: rsc];
In either the InformationSegmentController class or ResultSegmentController class, I tried to Log this:
NSLog(#"%#",self.parentViewController);
But unfortunately, it is a nil. How can I get the parentViewController correctly? Do I have to use the prepareForSegue?
// Question Update:
I found that I don't have to call addChildViewController method again if I create those childViewControllers directly in my storyboard.
I have tried to NSLog(#"%#", self.childViewControllers) in my AddInformationController and the result contains InformationSegmentController class and ResultSegmentController class.
But the problem is when I call NSLog(#"%#", self.parentViewController) on both childViewContorllers in viewDidLoad, the results is nil.
You have to try like this
//add childview
[self addChildViewController:aVC];
[self.view addSubview:aVC.view];
[aVC didMoveToParentViewController:self];
//remove
[self removeFromParentViewController];
[self didMoveToParentViewController:nil];
[self.view removeFromSuperview];
Hope it Helps you.
OR
another way to get PerentViewController in ChildViewControler is Make #property (strong, nonatomic) AddInformationController *ParentVC; in Your ChildViewController.h and assign viewController from your ParentViewController Like
InformationSegmentController *isc = [self.storyboard instantiateViewControllerWithIdentfier:#"InformationSegmentController"];
isc.ParentVC = self;
[self addChildViewController: isc];
Give identifiers to both the segues to your container views(suppose "InformationSegmentControllerSegue" and "ResultSegmentControllerSegue" ,namely) and use prepareForSegue in your AddInformationController like this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"InformationSegmentControllerSegue"]) {
InformationSegmentController *container1 = segue.destinationViewController;
}
else if([[segue identifier] isEqualToString:#"ResultSegmentControllerSegue"]) {
ResultSegmentController *container2 = segue.destinationViewController;
}
}
Hope this helps you.

prepareForSegue for Popover

I have returned to a project to make some minor changes and find that I'm getting a NSInvalidArgumentException presenting a popover. I'm almost certain that this worked previously. I'm using Xcode 6.3.1 and iOS 8.3 SDK.
I believe the issue is to do with the segue object being sent to prepareForSegue which is a UIStoryboardPushSegue - should it not be a UIStoryboardPopoverSegue if that is what is defined in the storyboard segue?
The error I'm receiving is -[UIStoryboardPushSegue popoverController]: unrecognized selector sent to instance
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DatePickerViewController *vc = (DatePickerViewController*)segue.destinationViewController;
[vc setQuestion:self.question];
[vc setDismissPopoverDelegate:self];
if([segue.identifier isEqualToString:#"CompletionDateSegue"])
{
[vc.datePicker setDate:self.question.completionDate animated:YES];
[vc setPropertyName:#"completionDate"];
}
else if ([segue.identifier isEqualToString:#"TargetCompletionDateSegue"])
{
[vc.datePicker setDate:self.question.targetCompletionDate animated:YES];
[vc setPropertyName:#"targetCompletionDate"];
}
UIStoryboardPopoverSegue *popoverSegue = (UIStoryboardPopoverSegue *)segue;
[popoverSegue.popoverController setPopoverContentSize:CGSizeMake(320, 256) animated:YES];
}

Correct adding and UIViewController to another

Tonight one faced with this:
- (void)loadView {
VC *vc = [[VC alloc] initWithStyle:UITableViewStyleGrouped];
[self addChildViewController:vc];
[vc removeFromParentViewController];
[self setView:vc.view];
}
and got a bomb:
uncaught exception 'UIViewControllerHierarchyInconsistency', reason:
'A view can only be associated with at most one view controller at a time!
Q: How we can directly add vc and all its functionality to current ViewController without AddSubView?
Add your table view controller's view as a subview of the current view. You shouldn't call removeFromParentViewController on vc because that would essentially negate the line before. It's also a good idea to set the frame to match the parent.
- (void)loadView
{
[super loadView]; // this will create a basic view
VC *vc = [[VC alloc] initWithStyle:UITableViewStyleGrouped];
[self addChildViewController:vc];
vc.view.frame = self.view.bounds;
vc.view.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
[self.view addSubview:vc.view];
[vc didMoveToParentViewController:self];
}

Passing data to UIViewController when using modal

I have two view controllers, MainViewController and SecondViewController.
In my main view controller, I have data I pass to the second view controller like so:
-(IBAction)shareToSocial:(id)sender {
SecondViewController *view2 = (SecondViewsController *)[storyboard instantiateViewControllerWithIdentifier:#"PushToNext"];
view2.secTitle = self.MainTitle;
[self.navigationController setModalPresentationStyle: UIModalPresentationCurrentContext];
[self setModalPresentationStyle:UIModalPresentationCurrentContext];
}
Where both secTitle and MainTitle are NSStrings for each controller. From what I've read, by setting view2.secTitle to self.MainTitle, when SecondViewController pops in I my view2.secTitle will have the same value as MainTitle. So if MainTitle is "Hello World" then I open secondViewController, secTitle would also be "Hello World". However, I've been getting null with secTitle even though I am setting the data for it.
If I use pushViewController instead of modal, the values are passed between the two controllers fine. So I'm not sure if I'm doing anything wrong here exactly.
I've also tried using [view2 setSecTitle:MainTitle] to no avail.
There's not much code on my SecondViewController but here's how it looks:
-(IBAction)showMessage:id(sender){
NSLog(#"test: %#", self.secTitle);
}
-(IBAction)closeMessage:id(sender){
[self dismissViewControllerAnimated:YES completion:nil];
}
Also, I've noticed that when I used dismissViewControllerAnimated on SecondViewController to close it and go back to the MainViewController, a black empty screen shows for a few seconds before showing the Main View and touch events on MainViewController is not detected anymore.
Please help.
Could you use performSegueWithIdentifier and prepareForSegue? If you've got your views in your storyboard and set up a segue between them, given it an identifier and set the style to modal you should be able to do this:
-(IBAction)shareToSocial:(id)sender {
[self performSegueWithIdentifier:#"modelToNextSegue" sender:self];
}
Then in prepareForSegue method you pass your values:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
SecondViewController *view2 = [segue destinationViewController];
view2.secTitle = self.MainTitle;
}
Try this:
SecondViewController *view2 = (SecondViewsController *)[storyboard instantiateViewControllerWithIdentifier:#"PushToNext"];
view2.secTitle = self.MainTitle;
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:view2];
[nav setModalPresentationStyle: UIModalPresentationCurrentContext];
[self setModalPresentationStyle:UIModalPresentationCurrentContext];

iOS Storyboard - Navigation Controller Not Working

I am having trouble with a Navigation Controller in my iOS project which uses Storyboards.
The main part of the project is a UITabBar. When the app loads for the very first time the screen RegisterViewController is presented:
When the user taps on the "Register" button a HTTP POST request is made, then upon receiving the response (JSON object) the screen QuestionnaireViewController is presented using:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
QuestionnaireViewController *questionnaireViewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"QuestionnaireView"];
[questionnaireViewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[questionnaireViewController setQuestionsAndAnswers:_questionsAndAnswers];
[self presentViewController:questionnaireViewController animated:NO completion:nil];
When the user taps on a cell in QuestionnaireViewController a message is sent to prepareForSegue:sender:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UINavigationController *navigationController = segue.destinationViewController;
AnswersViewController *answersViewController = [[navigationController viewControllers] objectAtIndex:0];
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSArray *answers = [[_questionsAndAnswers objectAtIndex:indexPath.row] objectForKey:#"answers"];
[answersViewController setAnswers:answers];
}
At this point the app crashes with an error of:
-[AnswersViewController viewControllers]: unrecognized selector sent to instance.
Below is a more comprehensive overview of my storyboard, which may help in understanding where I have gone wrong:
I am stumped as to how to fix this, and am hoping that someone out there is able to help.
Thanks,
Nick
First, you should present the navigation controller, not its root view controller. Then when you want to populate the root view controller with some data, you need to reference it as the navigation controller's root view controller:
UINavigationcontroller *questionnaireNavController = [self.storyboard instantiateViewControllerWithIdentifier:#"QuestionnaireNavigationController"];
[questionnaireNavController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
QuestionnaireViewController *qvc = (QuestionnaireViewController *)[questionnaireNavController topViewController];
[qvc setQuestionsAndAnswers:_questionsAndAnswers];
[self presentViewController:questionnaireNavController animated:NO completion:nil];
Second, in prepareForSegue:sender: you don't need to reference a navigation controller at all:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
AnswersViewController *answersVC = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSArray *answers = [[_questionsAndAnswers objectAtIndex:indexPath.row] objectForKey:#"answers"];
[answersVC setAnswers:answers];
}
You are not getting the navigationController properly. Instead of segue.destinationViewController, use self.navigationController
By calling segue.destinationViewController, you are getting a pointer to the VC you are segueing to (AnswersViewController) which doesn't understand the message viewControllers because it is not a UINavigationController.
Also the AnswersViewController is objectAtIndex:1 I believe, check this though.

Resources