如何在没有 StoryBoard 的两个 ViewController 之间使用委托?
Posted
技术标签:
【中文标题】如何在没有 StoryBoard 的两个 ViewController 之间使用委托?【英文标题】:How to use delegate between two ViewController without StoryBoard? 【发布时间】: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”?
【参考方案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
完成后从内存中删除,因为您没有保留它的引用。您要么需要创建一个属性来保存它,要么将它推送到导航堆栈上以便导航控制器保存它。
有多种方法可以解决这个问题:
-
不要创建新的
viewController2
,而是查找对已显示在屏幕上的引用(如果它在屏幕上)。
如果它不在导航堆栈中,请将 vc2
添加到导航堆栈 [self.navigationController pushViewController:vc2 animated:YES];
(假设您有导航控制器)。
如果不在堆栈上,并且不打算使用导航控制器,则以模态方式呈现vc2
,例如[self presentViewController:vc2 animated:YES completion:nil];
【讨论】:
您还可以提到,本地vc2
(实例)基本上在-viewDidLoad
超出其范围后立即释放,他们需要通过引用保持实例处于活动状态在范围之外。以上是关于如何在没有 StoryBoard 的两个 ViewController 之间使用委托?的主要内容,如果未能解决你的问题,请参考以下文章
xcode storyboard Container View - 如何访问视图控制器
以编程方式覆盖 loadView 和设置 rootViewController,没有 Storyboard
如何在没有 segue 和 storyboard 编程的情况下传递数据?
iOS最牛逼得自定义View方式支持storyboard显示
使用 UITabbarController 和 UINavigationController 从 storyboard 调用 View
如何使用 didSelectRowAtIndexPath(在 Swift 中)在两个 Storyboard 之间传递日期?