从iOS中的App Delegate调用当前视图控制器中的方法

时间:2011-05-03 17:42:42

标签: iphone objective-c ios

我有两个视图控制器(BuildingsViewController和RoomsViewController),它们都使用名为upload的App Delegate中的一个函数。 upload函数基本上执行HTTP请求,如果成功或不成功,则触发uialertview。这很好。

我正在努力的部分来自app delegate的connectionDidFinishLoading方法。我需要能够通过该视图控制器的viewWillAppear方法基本刷新当前视图控制器。在每个视图控制器的viewWillAppear函数内部,我有代码来确定底部工具栏上的按钮。

我想让每个视图控制器工具栏中的“上传”按钮在通过应用代表完成上传时自动删除。

我尝试在app委托的[viewController viewWillAppear:YES]方法中执行connectionDidFinishLoading,但它永远不会被调用。

我希望我足够清楚。非常感谢任何帮助。

感谢。

4 个答案:

答案 0 :(得分:86)

如果视图已经显示,要进行视图刷新,请不要调用viewWillAppear。你想要做的是以下几点:

在通知后触发ConnectionDidFinishLoading方法

[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshView" object:nil];

viewController观察此通知时。您可以通过将此代码添加到init或viewDidLoad方法

来实现
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshView:) name:@"refreshView" object:nil];

现在在-(void)refreshView:(NSNotification *) notification中实施viewController方法,根据自己的喜好管理视图。

答案 1 :(得分:3)

如果您的目标是iOS 4.0及更高版本,则可以使用窗口的rootViewController属性来获取当前的视图控制器。

[window.rootViewController viewWillAppear];

如果您希望您的应用程序在iOS 4.0之前的版本上运行,那么您可以向应用程序委托添加一个实例变量,以记住哪个视图控制器称为upload方法,让控制器将自身作为参数发送

- (void)upload:(UIViewController *)viewController {
    self.uploadingViewController = viewController; // This is the property you add
    ...
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.uploadingViewController viewWillAppear];
    self.uploadingViewController = nil;
}

您还应考虑使用其他方法重新加载按钮,例如reloadButtons,因为它与此案例中出现的视图无关。然后,您将在viewWillAppear内调用该方法。

答案 2 :(得分:2)

第1步:

在App Delegate .h文件中,您需要声明如下协议:

@protocol AppConnectionDelegate <NSObject>
@required
   -(void)connectionFinished:(NSObject*)outObject;
@end

在同一个文件中,添加如下的ivar:

id *delegate;

将ivar声明为属性:

@property (nonatomic, assign) id<AppConnectionDelegate> delegate;

在App Delegate .m文件中,合成ivar:

@synthesize delegate;

在App Delegate .m文件中,在connectionDidFinishLoading上执行:

if([self.delegate respondsToSelector:@selector(connectionFinished:)])
{
   [self.delegate connectionFinished:objectYouWantToSend];
}

在viewcontroller的.h文件中,通过导入对app委托文件的引用来实现AppConnectionDelegate:

#import "AppDelegate_iPhone.h" //if using iPhone
#import "AppDelegate_iPad.h" //if using iPad

在同一个文件中,在接口声明的第一行末尾执行:

@interface AppDelegate_iPhone : AppDelegate_Shared <AppConnectionDelegate>

相应地声明ivars:

AppDelegate_iPhone *appDelegate; //if using iPhone
AppDelegate_iPad *appDelegate; // if using iPad

在viewDidLoad()的viewcontroller的.m文件中,使用以下命令获取对您的app delegate的引用:

如果iPhone;

appDelegate = (AppDelegate_iPhone*)[[UIApplication sharedApplication] delegate];

如果iPad:

appDelegate = (AppDelegate_iPad*)[[UIApplication sharedApplication] delegate];

然后通过执行以下操作将viewcontroller设置为viewDidLoad()中的委托:

appDelegate.delegate = self;

现在您需要在.m文件中简单地实现connectionFinished方法:

- (void)connectionFinished:(NSObject*)incomingObject
{
//Do whatever you want here when the connection is finished. IncomingObject is the object that the app delegate sent.
}

现在,无论何时调用app delegate的connectionDidFinishLoading,都会通知视图控制器。

[如果您使用connectionFinished回调设置appDelegate.delegate = nil是最佳做法]

经过试用和测试。如果您有任何疑问,请发表评论......

- EDIT--这是NSNotification的强大替代方案。我根据要求使用两者。我用来决定在使用NSNotification或使用协议的委托回调之间的过程只是:

通知:
   一个发件人,多个听众    发送者和听众之间无法参考    无需发送复杂/多个对象

对于使用协议的委托回调:
   一个发送者,有限(通常是1个)听众    发送者和听者之间的参考是可能的    要发送复杂/多个对象(例如,需要发送的响应对象)

我知道通过通知可以发送对象,但我更喜欢协议。
--edit -

答案 3 :(得分:0)

更糟糕的是,您可以让两个视图控制器都遵循一个简单的方法协议,该协议将删除该按钮并刷新视图。然后在你的connectionDidFinishLoading方法中,既然你知道你的视图控制器必须遵守那个协议,那么按照你的设计,你只需要执行类似

的操作。
ViewController<MyProtocol> curView = (Get the current view controller somehow);
[curview refreshView];