两个不同的视图控制器如何相互通信

时间:2012-02-03 11:09:03

标签: ios

我有一个带标签栏的应用程序和3个不同的View Controller。其中一个imanage是我通过Interface Builder(storyboard)设计的UItableView,我在Inspector中设置了它的视图控制器类 - >检查员身份 - >我在那里设置了类字段,因此,当这个视图控制器被实例化时,我无法控制,因为当用户点击标签栏时,它通过故事板完成。请注意,我是目标C和iOS编程的新手。

我面临的问题,我也在使用远程通知。因此,当我在AppDelgate类的“didReceiveRemoteNotification”中收到远程通知消息时。我需要更新UI界面(在ViewController之上),但问题是我没有从我的AppDelgate类到这个ViewController的引用(指针)(或者我?)。这个ViewController由storyboard实例化,也没有以编程方式实现,否则我可以保留对它的引用。

我做了一些阅读,我知道我可以通过NSNotification进行这种沟通,但我认为这对于一个可能出现的问题来说是一种矫枉过正,因为我是新手,我对iOS并不完全了解发展。

谢谢,

3 个答案:

答案 0 :(得分:14)

NSNotifications易于使用,可能是正确的解决方案。

在需要发送消息的app委托中,只需输入:

[[NSNotificationCenter defaultCenter] postNotificationName:@"MyNotification" object:someObjectYouWantToPassCouldBeAppDelegateOrRemoteNotificationObjectOrAnything];

在接收消息的视图控制器中,输入:

-(void)viewDidLoad
{
    [super viewDidLoad];

    //you can add as many of these as you like to handle different notifications
    [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(handleNotification:) name:@"MyNotification" object:nil];
}

-(void)viewDidUnload
{
     //make sure you remove every observer you've added here 
     [[NSNotificationCenter defaultCenter] removeObserver:self name:@"MyNotification" object:nil];

     [super viewDidUnload];
}

-(void)dealloc
{
    //clean up in case viewDidUnload wasn't called (it sometimes isn't) 
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

//use a different handler method for each notification
//the method name should match the selector in your observe call in viewDidLoad
-(void)handleNotification:(NSNotification *)notification
{
    WhateverClassOfObjectYouWerePassing *object = notification.object;

    //now you have a reference to the object that was passed from your app delegate
}

对于您要调用的不同方法,只需要一个新的通知名称和一个新的处理程序方法。

答案 1 :(得分:5)

您的应用代表将有一个指向应用程序窗口的窗口属性。

Window Property具有-rootViewController属性/方法。

对于基于选项卡的应用程序,它会返回TabViewController。

每个TabViewController都有一个方法-(NSArray *)viewControllers,它返回Tab中的ViewControllers。这些按顺序排列。

访问您的应用程序AppDelegate使用[[UIApplication sharedApplication]委托]

一旦你拥有了这些viewcontrollers,你就会知道自从你将它们添加到XIB文件中之后所有这些都是viewController。并且可以执行你的方法

答案 2 :(得分:1)

<强> 1。沟通两个ViewControllers

如果您想要传达两个ViewControllers,您应该使用Apple推荐的@protocol


ViewController1.h


 @interface ViewController1 : UIViewController<ViewController2Delegate, ViewController2DataSource>
@end

ViewController1.m


- (IBAction)goToViewController2:(id)sender{
    if(viewController2 == nil) {
        ViewController2 *viewController = [[ViewController2 alloc]
                                               initWithNibName:@"View2" bundle:[NSBundle mainBundle]];
        viewController2 = viewController;
    }
    //...
    viewController2.delegate = self;
    viewController2.dataSource = self;
    [self.navigationController pushViewController:viewController2 animated:YES];
}


- (NSString)viewController:(ViewController2 *)controller itemForSomethingAtIndex:(NSInteger)index{
    //Send to viewController2 what it needs
    return [items objectAtIndex: index];
}
- (void)viewController:(ViewController2 *)controller didFinishEnteringItem:(NSString *)item{
    //Handle the result from the viewController2
    NSLog(@"result: %@", item);
}

ViewController2.h


#import <UIKit/UIKit.h>


// Define your delegate methods to return items to the delegate of this viewController
@protocol ViewController2Delegate <NSObject>
    - (void)viewController:(ViewController2 *)controller didFinishEnteringItem:(NSString *)item;
@end

// Define your dataSource methods to send items from the dataSource to this viewController
@protocol ViewController2DataSource <NSObject>
    - (NSString)viewController:(ViewController2 *)controller itemForSomethingAtIndex:(NSInteger)index;
@end



@interface ViewController2 : UIViewController

@property (nonatomic) id <ViewController2Delegate> delegate;
@property (nonatomic) id <ViewController2DataSource> dataSource;

@end

ViewController2.m


#import "ViewController2.h"

@interface ViewController2 ()
@end

@implementation ViewController2

@synthesize //...;

- (void)someMethod {
    //Get someThing from controller1
    NSString *item = [dataSource viewController: self itemForSomethingAtIndex:0];

    //Return someThing to controller1
    [delegate viewController: self didFinishEnteringItem: item];
}

<强> 2。使用viewController传递backgroundTask

如果您想传达后台任务或处理推送通知,请使用@ NickLockwood的answer。但如果viewController没有加载,这不会工作。在这种情况下,您应该在AppDelegate中处理它:


//Get the appDelegate instance
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//And call your custom method to show what it needs
[appDelegate customMethod];

您的自定义方法应该像控制器一样调用控制器:

AppDelegate > RootController > ViewController1 > ViewController2 > myMethod 
//do something if viewController2 is visible to the user or push it before do something.
//if you use navigation controller, then you need to ask for the position and className