简体   繁体   English

在prepareForSegue中传递对ViewController的引用

[英]Pass a reference to ViewController in prepareForSegue

I have 2 view controllers, call them ViewController1 and ViewController2. 我有2个视图控制器,称之为ViewController1和ViewController2。 A modal segue is invoked from ViewController1 when I want to load ViewController2. 当我想加载ViewController2时,从ViewController1调用模态segue。 I have a method in ViewController1 that needs to be called at some point when ViewController2 is showing. 我在ViewController1中有一个方法需要在ViewController2显示时调用。 My idea is to have a property in ViewController2 that is a reference to ViewController1 so that I can get access to the method. 我的想法是在ViewController2中有一个属性,它是对ViewController1的引用,以便我可以访问该方法。

@property (strong, nonatomic) ViewController1 *vc1Reference;

This property would be set in the prepareForSegue method like so: 这个属性将在prepareForSegue方法中设置,如下所示:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {   // 1
    if ([[segue identifier] isEqualToString:@"sequeToVC2"]) {            // 2
        ViewController2 *vc2 = segue.destinationViewController;          // 3
        vc2.vc1Reference = (ViewController1*)segue.sourceViewController; // 4
    }
}

However line 4 gives me this error: Implicit conversion of an Objective-C pointer to 'int *' is disallowed with ARC. 但是第4行给出了这个错误:ARC不允许将Objective-C指针隐式转换为'int *'。

How am I supposed to set the reference? 我该怎么设置参考?

You are on the right track, but the correct way to do this is to use a delegate. 您走在正确的轨道上,但正确的方法是使用委托。

You declare a delegate property in your vc2 @interface : 您在vc2 @interface声明了一个委托属性:

@property (nonatomic, weak) id <vc2delegate> delegate   //[1] (in vc2.h)

And you set the delegate in your prepareForSegue : 然后在prepareForSegue设置委托:

vc2.delegate = self;    //[2] (in vc1.m)

('self' is the correct reference for vc1, from vc1) ('self'是vc1的正确参考,来自vc1)

In vc2 you define a protocol, which is the method that you expect vc1 to respond to from vc2. 在vc2中,您定义了一个协议,这是您希望vc1从vc2响应的方法。 Put this in vc2.h, above your @interface 把它放在@interface上方的vc2.h中

@protocol vc2delegate           //[3] (in vc2.h)
- (void) delegateMethod;
@end

Then you have to ensure you implement that method in vc1. 然后,您必须确保在vc1中实现该方法。 Also you need to let vc1 know to conform to the delegate. 您还需要让vc1知道符合委托。 Import vc2 into vc1.h, and on your @interface line in vc1 add the protocol name in angle brackets: 将vc2导入vc1.h,并在vc1中的@interface行中将协议名称添加到尖括号中:

#import vc2.h

@interface vc1 <vc2delegate>     //[4] (in vc1.h)

This arrangement allows vc2 to pass a method to vc1 without having to #include vc1 or know anything else about it. 这种安排允许vc2将方法传递给vc1,而不必#include vc1或了解其他任何内容。

more detail... 更多详情...

  1. This is the correct form of your 这是你的正确形式

     @property (strong, nonatomic) ViewController1 *vc1Reference; 

    Note the use of weak reference. 注意使用weak引用。 You don't want to make a strong reference as you don't really want to have anything to do with the delegate except to know it can handle methods you specify in your protocol. 您不希望strong引用,因为您不想与委托有任何关系,除非知道它可以处理您在协议中指定的方法。 The delegate is often the object that created the delegator, creating a strong reference back in the other direction can cause memory leaks as neither object can go out of existence. 委托通常是创建委托者的对象,在另一个方向上创建strong引用会导致内存泄漏,因为这两个对象都不会存在。

  2. this is the correct form of your line: 这是你的行的正确形式:

     vc2.vc1Reference = (ViewController1*)segue.sourceViewController; 

    Note that we are NOT using type/casting in 1 or 2. For maximum code reuse/decoupling we dont want to make any suppositions on the type of object at either end of the segue. 请注意,我们不使用1或2中的类型/强制转换。为了最大限度地重用代码/解耦,我们不希望对segue任何一端的对象类型做出任何假设。 I am assuming that your 'prepareForSegue' is in vc1. 我假设你的'prepareForSegue'在vc1中。 If it is not then the line would look like this: 如果不是那么该行看起来像这样:

     vc2.delegate = segue.sourceViewController 
  3. This is the protocol declaration. 这是协议声明。 It goes in the header file for vc2. 它位于vc2的头文件中。 vc2 is publishing it's expectations of any object that chooses to become its delegate. vc2正在发布它对任何选择成为其委托的对象的期望。 vc2 will be sending messages according to this protocol so any delegate needs to respond in the correct way. vc2将根据此协议发送消息,因此任何委托都需要以正确的方式响应。 You can guard against failure in vc2 by using this kind of message-passing 您可以使用这种消息传递来防止vc2中的故障

     if (self.delegate respondsToSelector:@selector('delegateMethod') { [self.delegate delegateMethod]; } 

    (that is an example of the kind of message passing you would use in vc2 to communicate back to vc1. you can obviously pass paremeters and get returned results back if need be) (这是您在vc2中用于与vc1进行通信的消息传递类型的示例。如果需要,您可以显然传递参数并返回返回的结果)

  4. this is a helper for the compiler which can issue you with warnings if you fail to implement the protocol. 这是编译器的帮助程序,如果您未能实现协议,它可以向您发出警告。

    Finally somewhere in your object definition you need to implement the method: 最后在对象定义的某处,您需要实现该方法:

     - (void) delegateMethod { // someaction; } 

I ran into something similar the other day. 前几天我碰到了类似的东西。 I ended up creating a delegate for vc2, and using 我最终为vc2创建了一个委托,并使用了

vc2.delegate = self;

in the segue instead. 相反,在塞古里。 Would this solve your problem? 这会解决你的问题吗? If you need help setting up the delegate, let me know and I'll do my best to help! 如果您需要帮助设置代表,请告诉我,我会尽力帮助您!

Just add a delegate to your the ViewController that you are accessing the delegate on, XCode / Obj-C seems to do the right thing afterwards. 只需将一个委托添加到您正在访问该委托的ViewController上,之后XCode / Obj-C似乎做了正确的事情。

Before: 之前:

@interface ViewController2 : UIViewController

@end

After: 后:

@interface ViewController2 : UIViewController
  @property (nonatomic, weak) id <UIPageViewControllerDelegate> delegate;
@end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM