从另一个类访问viewController的方法

问题描述:

我一直在尝试使用UIButton动作来调用不同类(AppViewController)中的方法。我首先尝试在UIButton's呼叫类(caller.m)中创建视图控制器的一个实例,然后调用该方法,但保留导致EXC_BAD_ACCESS从另一个类访问viewController的方法

我意识到我需要指向视图控制器的同一个实例,我现在努力确保视图控制器实例在caller.m.

正确声明我的AppViewController *viewController声明中AppDelegate,所以我的想法是从caller.m引用同一个实例。

#import "caller.h" 
#import "AppDelegate.h" 

@implementation caller 

- (id)initWithFrame:(CGRect)frame { 
... 
[btnSplash addTarget:viewController action:@selector(loadSplashView) forControlEvents:UIControlEventTouchUpInside]; 
.... 
} 

但是,viewController仍然显示为未声明。我尝试了其他一些事情,但知道我可能错过了一些基本的东西。

:::: UPDATE ::::

好了,原来我需要创建下面这样的目标“的viewController”实际上是宣布并指向正确的实例:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
AppViewController* viewController = appDelegate.viewController; 

现在正在正确调用视图控制器类中的方法。

对于这个问题更清楚的解释,更全面的版本,请到这里: Objective-c basics: Object declared in MyAppDelegate not accessible in another class

点击,将被捕获并在AppViewController执行的按钮时,您应该发表一个NSNotification。

所以这应该是: 发信人类:

[btnSplash addTarget:self 
       action:@selector(loadSplashView) 
    forControlEvents:UIControlEventTouchUpInside]; 

-(void)loadSplashView:(id)sender 
{ 
[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_name" object:some_sender_object]; 
} 

在目标类: 注册,即可获得该通知在视图的负荷:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(some_function:) name:@"notif_name" object:nil]; 

定义要采取的行动中本类:

-(void) some_function:(NSNotification *)notif { 
    //do something 
    // to access the object do: [notif object] 
} 
+0

当我调用视图控制器的不同副本的方法时,我实际上正在做一个NSLog。但在这里,我甚至没有编译,因为viewController看起来没有声明。 – 2011-04-10 12:13:30

+0

如果你使用NSNotification,目标应该是“self” – 2011-04-10 12:15:46

+0

[btnSplash addTarget:self action:@selector(loadSplashView)forControlEvents:UIControlEventTouchUpInside];并在 - (void)loadSplashView {[[NSNotificationCenter defaultCenter] postNotificationName:@“notif_name”object:some_sender_object];} – 2011-04-10 12:17:13

有多个乐的方式为对象提起诉讼,与其他物体的沟通和/或观察改变他们感兴趣的,包括:

  1. UIControl目标/行动绑定
  2. 协议
  3. 键/值观察(KVO)
  4. 通知书

我不认为在这种情况下通知是你想要的。当发布通知的对象不关心哪些对象正在观察通知,并且可以有一个或多个观察者时,通知是最合适的。在按下按钮的情况下,通常只需要特定的对象来处理该操作。

我会推荐使用协议。您会在iOS框架中看到很多使用的协议,基本上任何具有delegate属性的类通常都会定义委托对象需要遵守的协议。该协议是两个对象之间的契约,使得定义该协议的对象知道它可以与符合该协议的对象进行通信,而不用考虑其类别或目的的任何其他假设。

下面是一个示例实现。道歉,如果有任何错误/遗漏。

在caller.h(I假定呼叫者是一个UIViewController):

@class Caller 

@protocol CallerDelegate 
    - (void)userDidSplashFromCaller:(Caller *)caller; 
@end 

@interface Caller : UIViewController 
    id <CallerDelegate> delegate; 
@end 

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

@end 

在caller.m:

在otherViewController.m
@implementation Caller 

@synthesize delegate; 

- (void)viewDidLoad { 
    // whatever you need 
    // you can also define this in IB 
    [btnSplash addTarget:self forAction:@selector(userTouchedSplashButton)]; 
} 

- (void)dealloc { 
    self.delegate = nil; 
    [super dealloc]; 
} 

- (void)userTouchedSplashButton { 
    if (delegate && [delegate respondsToSelector:@selector(userDidSplashFromCaller:)]) { 
     [delegate userDidSplashFromCaller:self]; 
    } 
} 

// this assumes caller is pushed onto a navigationController 
- (void)presentCaller { 
    Caller *caller = [[Caller alloc] init]; 
    caller.delegate = self; 
    [self.navigationController pushViewController:caller animated:YES]; 
    [caller release]; 
} 

// protocol message from Caller instance 
- (void)userDidSplashFromCaller:(Caller *)caller { 
    NSLog(@"otherVC:userDidSplashFromCaller:%@", caller); 
} 

[EDIT :CLARIFICATIONS]

我在再次查看您的问题和代码后意识到,我做了一些假设,您的代码中可能不是这样。您很可能仍应使用协议,但集成我的示例的确切方式取决于您的应用程序。我不知道什么类Caller在您的应用程序中,但不管它是什么,它处理UIButtons,因此它很可能是视图控制器或视图。

你对没有正确的appViewController实例的评论让我怀疑你是否理解类和类的实例之间的区别。如果我的回答对你没有帮助,请张贴更多的代码来显示你如何创建和呈现你的视图控制器,以及你如何配置按钮,我可以尝试澄清我的答案。

+0

谢谢你的帮助。这实际上还是很好的信息,但我不确定我是否在描述OP上的问题方面做得最好。但是,在更为一般的解释之后,我能够找到一个解决方案:http:// *。com/questions/5611972/objective-c-basics-object-declared-in-myappdelegate-not-accessible-in-another-cl – 2011-04-11 05:35:53

+0

没问题,你的其他问题听起来像是完全不同的东西。我不知道你真正需要的只是了解属性。请注意,在我上面的示例中,“委托”是一个属性。有关更多信息,请注意属性主要是为iVar定义getter和setter的编译器快捷方式。 getter/setter方法是外部类在导入.h文件时知道的。快乐的编码! – XJones 2011-04-11 05:56:14

应用程序的各种对象之间的通信是设计级别决定。虽然iOS提供了在代码时间(属性)完成此操作的简洁方式 - 但它是通过硬耦合的。

真正的对象间通信不会在编译时绑定对象 - 这是只能通过遵循设计模式来保证的事情。

观察员&代表是两种最常用的模式,值得您学习when to use which one - see Observer vs Delegate