【问题标题】:How to use delegate between two ViewController without StoryBoard?如何在没有 StoryBoard 的两个 ViewController 之间使用委托?
【发布时间】:2018-02-05 15:35:46
【问题描述】:

我想触发从 viewController 到另一个 viewController 的消息。 我编码如下,但 viewController 没有调用委托。 我想在没有 stroyboard 的情况下调用代表。我只是想向另一个 viewController 发送消息。

viewController2.h

@protocol ViewController2Delegate;

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

@protocol ViewController2Delegate <NSObject>
- (void)showSomethingByDelegate;
@end

viewController2.m

#import "ViewController2.h"

@interface ViewController2 ()

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}
- (IBAction)buttonPressed:(id)sender {
    [self.delegate showSomethingByDelegate];
}

@end

viewController.m

#import "ViewController.h"
#import "ViewController2.h"

@interface ViewController ()
<ViewController2Delegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    ViewController2 *vc2 = [[ViewController2 alloc] init];
    vc2.delegate = self;

}
// Below method was not called by delegate.
- (void)showSomethingByDelegate {
    NSLog(@"Button Was Pressed!!!");
}


@end

【问题讨论】:

  • 我想当vc2 实际进入导航堆栈时,一定有一个 sn-p... >不同的 ViewController2 的实例最终会进入堆栈,并且任何更改都没有为此设置委托?
  • 如何导航到“ViewController”?

标签: ios objective-c delegates protocols viewcontroller


【解决方案1】:

让我举一个更简单的例子。

文件:firstVC.h

/* This define the protocol object,
 you can write methods required or optional the diference is when
 the protocol is used in a class, xcode show you a yellow warning with required methods
 like UITableViewDelegate, UITextFieldDelegate... */

@protocol firstVCDelegate <NSObject>

@required
- (void)didMessageFromOtherViewController: (NSString *)messageStr;

@optional
- (void)didOtherMessageNotRequired: (NSString *)messageStr;

@end

/* This is the definition of first UIViewController */

@interface firstViewController : UIViewController
@end


/* This is the definition of second UIViewController object with
 a property that is our protocol 'firstVCDelegate' */

@interface secondViewController : UIViewController

@property (nonatomic, weak) id <firstVCDelegate> firstVCDelegate;

- (void)executeDelegateProcess;

@end

文件:firstVC.m

#import "firstVC.h"

#pragma mark - First UIViewController with delegate

@interface firstViewController() <firstVCDelegate>
@end

@implementation firstViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Creating the 'secondViewController' object with delegate on this class
    secondViewController *svc = [secondViewController new];

    // Assign the delegate class
    [svc setFirstVCDelegate: self];

    // Run the delegate logic
    [svc executeDelegateProcess];
}

- (void)didMessageFromOtherViewController:(NSString *)messageStr
{
    // Receiving the message from the instance of our protocol in the 'secondViewController' class
    NSLog(@"MESSAGE #1: %@", messageStr);
}

- (void)didOtherMessageNotRequired:(NSString *)messageStr
{
    // Receiving the message in optional method
    NSLog(@"MESSAGE #2: %@", messageStr);
}

@end

#pragma mark - Second UIViewController

@implementation secondViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)setFirstVCDelegate:(id<firstVCDelegate>)firstVCDelegate
{
    if (firstVCDelegate)
        _firstVCDelegate = firstVCDelegate;
}

- (void)executeDelegateProcess
{
    // This method is only for demo
    // You can execute your delegate in the way you need to use

    if (_firstVCDelegate) {
        [_firstVCDelegate didMessageFromOtherViewController: @"Hello world, using the required method from secondViewController class"];

        [_firstVCDelegate didOtherMessageNotRequired: @"Hello code using the optional method"];
    }
}

@end

在你的 appDelegate.m 方法 didFinishLaunchingWithOptions 中你可以放这个,你需要 #import "firstVC.h"

self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
        self.window.autoresizesSubviews = YES;
        [self.window makeKeyAndVisible];

        [_window setRootViewController: [firstViewController new]];

执行并看到两条日志消息,希望对我有所帮助:)

【讨论】:

    【解决方案2】:
    ViewController2 *vc2 = [[ViewController2 alloc] init];
    

    这行代码并没有像你想象的那样做,这是创建ViewController2 的新实例并将其存储在变量vc2 中。绝不会(根据您的代码)将此变量添加到导航堆栈并显示在屏幕上。


    编辑
    同样正如 Holex 所注意到的,您的 vc2 变量将在 viewDidLoad 完成后从内存中删除,因为您没有保留它的引用。您要么需要创建一个属性来保存它,要么将它推送到导航堆栈上以便导航控制器保存它。

    有多种方法可以解决这个问题:

    1. 不要创建新的viewController2,而是查找对已显示在屏幕上的引用(如果它在屏幕上)。
    2. 如果它不在导航堆栈中,请将 vc2 添加到导航堆栈 [self.navigationController pushViewController:vc2 animated:YES];(假设您有导航控制器)。
    3. 如果不在堆栈上,并且不打算使用导航控制器,则以模态方式呈现vc2,例如[self presentViewController:vc2 animated:YES completion:nil];

    【讨论】:

    • 您还可以提到,本地vc2(实例)基本上在-viewDidLoad 超出其范围后立即释放,他们需要通过引用保持实例处于活动状态在范围之外
    猜你喜欢
    • 2019-01-18
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 2015-09-13
    • 2018-12-19
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    相关资源
    最近更新 更多