ios push controller view programmatically without storyboards or xib

11,306

Solution 1

I believe I understand what you're asking and you are almost on the right track here. You said that it works when you use [self performSegueWithIdentifier:@"pushMessage" sender:self]; but the value is not set.

So, declare an NSString "from" in your header and in the previous code delete the [self.navigationController pushViewController:CVC animated:YES];

//ViewControllerA.h

@property (copy, nonatomic) NSString *from;



//ViewControllerA.m

@synthesize from;

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
  from = [NSString stringWithFormat:@"%@", cell.from.text];

  [self performSegueWithIdentifier:@"pushMessage" sender:self];
}

Then you need to use the prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

 //ViewControllerA.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{

    if ([[segue identifier] isEqualToString:@"pushMessage"]) {

        ViewControllerB *vcb = [segue destinationViewController];

        [vcb setFrom:[self from]];
    }

}

EDIT

Well, I feel like this is a really wrong way to do it. But, this will satisfy all of your conditions asked in the question. I have checked and this does in fact work:

First, Go to your storyboard, click on the View Controller B, click on the identity inspector and change the Storyboard ID. Also click the check that says "Use Storyboard ID".

Identity Inspector

In your ViewControllerA:

//ViewControllerA.h

- (void)callViewControllerWithCellString:(NSString *)str;

//ViewControllerA.m

- (void)callViewControllerWithCellString:(NSString *)str
{
    NSString * storyboardName = @"Main";

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
    SecondViewController * vc = [storyboard instantiateViewControllerWithIdentifier:@"ViewControllerB"];
    [vc setFrom:str];

    [[self navigationController] pushViewController:vc animated:YES];

}


-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
    NSString *from = [NSString stringWithFormat:@"%@", cell.from.text];

    [self callViewControllerWithCellString:from];
}

Solution 2

So lets see if i understand this.

  1. You want the text from the clicked row passed to the view controller that you want to present
  2. You want to do this without using storyboards

Sounds simple enough. Check this out.

// I actually recommend this option
// Simply initialize your view controller with the text that you want to pass
ViewControllerB * VCB = [[ViewControllerB alloc] initWithText:from];

//  For this to work, you'll have to declare a new init method in your .h file like this
-(void)initWithText:(NSSTring *)text;

// You should also declare an iVar to store your text
NSString * fromText;

// and implement it in your .m file like this
-(void)initWithText:(NSString *)text
{
    self = [super init];
    if (self)
    {
        fromText = text;
    }
    return self;
}

// Or, you could do this. 
// In ViewControllerB.h, create a property
@property (nonatomic, strong) NSString * fromText;

// In ViewControllerB.m, synthesize it
@synthesize fromText;

// Then you can pass that property a value like this
ViewControllerB * VCB = [[ViewControllerB alloc] init];
VCB.fromText = from;

Solution 3

You can push views programmatically as well. You seem to do following

ViewControllerB *VCB = [[ViewControllerB alloc]init];
VCB.from = from;
[self.navigationController pushViewController:CVC animated:YES];

Which means you want to push VCB and not CVC. This change should fix your problem. You can also put a breakpoint in viewDidLoad to verify your new ViewController is loaded.

If you are using storyboard for VCB as well, I think you should do following --

ViewControllerB *VCB = [self.storyboard instantiateViewControllerWithIdentifier:@"VCBIdentifier"];

where VCBIdentifier is the identifier to your ViewControllerB marked in Identity Inspector -> StoryBoardID. With your current init, I think, it is creating a default viewcontroller which is blank/empty.

Solution 4

Variables shoudl be lower case.

Your ViewControllerB should be displaed. Do you create all view elements in there programatically too? If you don't then you better load it from a XIB or from the storyboard. You can do that without segueing to it.

But I guess it is much easer to overwrite the perpareForSegue: method and set the from property there. That is what perpareForSegue is made for when you need to do some customization programatically while using storyboards for all the easy stuff.

Solution 5

First off, you should check your code. You are pushing a viewController named CVC onto the navigation controller. I assume this is a typo.

Did you override ViewControllerB "initWithNibName:bundle:" as I see you are calling init. How would the ViewController know what nib to load if you didn't?

Also, it is recommended that you call [super viewDidLoad] in your viewDidLoad call.

Share:
11,306
denikov
Author by

denikov

Aspiring developer, learning to program and code on the fly. Thanks everyone for helping me with my questions

Updated on September 10, 2022

Comments

  • denikov
    denikov over 1 year

    In ViewControllerA I have a table with three rows of data right now (three messages). Clicking on a row, I'm trying to push to ViewControllerB with the text from one of the rows (the name). Problem I'm having is I'm trying to do everything programmatically, not using storyboard ids or storyboard segues. Is this possible? Here's what I have.

    ViewControllerA m.

    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
      Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
      NSString *from = [NSString stringWithFormat:@"%@", cell.from.text];
      ViewControllerB *VCB = [[ViewControllerB alloc]init];
      VCB.from = from;
      [self.navigationController pushViewController:VCB animated:YES];
      //using this^ creates a new view controller with a black screen but passes the variable
      //[self performSegueWithIdentifier:@"pushMessage" sender:self];
      using this^ shows my ViewControllerB perfectly but the value isn't set
    }
    

    ViewControllerB h.

    @property (strong, nonatomic) NSString *from;
    

    ViewControllerB m.

    -(void)viewDidLoad{
        NSLog(@"%@", from);
    }
    

    Is there a way to do this without initiating a new viewcontrollerB in VCA and getting the right push animation?