views:

689

answers:

2

Hi guys, I'm a beginner programmmer, this is for xcode - iPhone. although i made alot of my iPhone app but i seem to lack some understanding of how a simple communication might work.

Specially when I've got 2 ViewControllers.

And I wana call one function of a ViewController from another ViewController. Both are under a tabbarController. What I want to achieve is When I'm in ViewA, after tapping on a tableCell, I Should Invoke a method of ViewB and the NavigationBar of ViewB pushes to viewDetail.

The Following is the code i'm using in ViewControllerA.h (where I'm calling a method)

@class ViewControllerB;
@interface SmartDDxViewController : UIViewController {

    IBOutlet UITableView *tableView;
    ViewControllerB *xViewController;


}
@property (nonatomic, retain) UITableView *tableView;
@property (nonatomic, retain) ViewControllerB *xViewController;

And this is what I use to invoke it..ViewControllerA.m

ViewControllerB *ddViewController = [[ViewControllerB alloc] init];
self.xViewController = ddViewController; 
[xViewController InitialiseDetailWithId:2 title:@"HEYA"];

Heres the InitialiseDetailWithId code: in ViewControllerB.m

-(void)InitialiseDetailWithId:(NSInteger)pkey title:(NSString *)tt{

    NSLog(@"InitialiseDetailC=========================================");
    AppDelegate *appDelegate = (Smart_DifferentialsAppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate GetConditionDetailsWithId:pkey];
    DDisViewController *viewController= [[DDisViewController alloc] initWithNibName:@"DetailView" bundle:nil];
    viewController.title = tt;
    [self.NavBar pushViewController:viewController animated:YES];
    //[tt release];
    [viewController release];
    viewController = nil;  
    [self say:@"HEYA"]; //this is ALERTVIEW box that displays HEYA
}

I'm getting all information fine, and the alertview does get displayed. But when I chose that View in TabBar, its not pushed.

A: 

In each of your view controllers, you might want to add a instance variable/property to keep track of the other view controller.

you might have for example:

@interface ThisViewController : UIViewController {
    SomeViewController  *sViewController;
// other instance variables
}
@property (nonatomic, retain) SomeViewController     *sViewController;

This not only makes it easier to call methods from the other view controller and access its public properties, but it also allows you an easier way of flipping between the two (with or without animation).

mahboudz
thanks for your reply friend,.. i figured that out but got a new problemo.. could ya please read the question again!, myBad!
Straight access to view controllers is most of the time a bad idea. It is a bad design with circular references that can/will lead to memory leaks.
PeyloW
A: 

Do not use direct access between view controllers, instead use the delegate pattern. Define your controller like this:

@protocol ViewControllerAInitDelegate;
@interface ViewControllerA : UIViewController {
  IBOutlet UITableView *tableView;
  id<ViewControllerAInitDelegate> initDelegate;
}
@property (nonatomic, retain) UITableView *tableView;
@property (nonatomic, assign) ViewControllerAInitDelegate *initDelegate;
@end

@protocol ViewControllerInitDelegate
-(void)initializeDetailWithId:(NSInteger)pkey title:(NSString)tt;
@end

So in

Now let your application delegate conform to the ViewControllerInitDelegate protocol. It should look something like this:

@interface AppDelegate : NSObject <UIApplicationDelegate, ViewControllerInitDelegate> {
  IBOutlet UITabBarControler* tabBarController;
  IBOutlet ViewControllerA* controllerA;
  IBOutlet ViewControllerB* controllerB;
}
@end;

The AppDelegate should know about both ViewControllerA, and ViewControllerB, but neither of the view controller should know about each other. This way it will be much easier to debug and extend your app.

PeyloW
your solution makes the app neat, no doubt, but I thought I'd this for two reasons, 1 being, ViewAController belongs to TabItem1 and FROM this Controller, I want to go to tabItem2 that displays ViewBController that is PUSHED to another DetailView. I'm not sure how the pushing would work via appDelegate, Well, its not working in my solution too.. anyway,
Your AppDelegates knows about all it's tabs, so it (if anything) should know how to push a new controller. `[[self.tabBarController.viewControllers objectAtIndex:1] pushViewController:newController animated:YES];` or something equally simple should do the trick.
PeyloW
Brother, i implemented as you said, I have some stuff confused, Like i should have a new method in appDelegate? that should PushViewController 1 and show Tab1, and all this i have to do from anotherViewcontrollerB, probably like [appdelegate NewMethodinAppDel: sd: ]; something like that??
Pretty much. The whole idea is that if you see your controllers a tree, then each controller should only know about it's children. If a child needs to callback to a parent then it should be done in a delegate protocol. This way you avoid circular dependencies, where A have requirements on B and B have requirements on A.
PeyloW