如何将方法移出应用程序委托?

Posted

技术标签:

【中文标题】如何将方法移出应用程序委托?【英文标题】:How to move methods out of app delegate? 【发布时间】:2015-04-25 08:49:52 【问题描述】:

我正在尝试将方法移出应用程序委托,而是使用单独的视图控制器来符合协议。 旧的应用程序委托是:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    self.qnaire = [[VRQuestionnaire alloc] initWithFile:[[NSBundle mainBundle] pathForResource:@"set1"
                                                                                        ofType:@"json"]];

    self.navController = (UINavigationController *)self.window.rootViewController;
    [self prepareForQuestion:self.qnaire.firstQuestion animated:NO];

    return YES;


/* Set up the question view controller with a question and push onto the nav stack
 */
- (void)prepareForQuestion:(VRQuestion *)question animated:(BOOL)animated;

    VRQuestionViewController *qvc = (VRQuestionViewController *)[self.navController.storyboard instantiateViewControllerWithIdentifier:@"QuestionViewController"];
    qvc.delegate = self;

    qvc.question = question;
    [self.navController pushViewController:qvc animated:animated];


/* Delegate that gets called every time a question is answered. This loads the next question and pushes it onto the nav stack.
 It also pushes a pointer to the question and result to a linked-list called firstAnswer->nextAnswer->nextAnswer, etc.

 When the next question returns nil we know we've finished as there are no more questions and log linked-list to console.
 */
- (void)questionViewController:(VRQuestionViewController *)controller didAnswerQuestion:(VRQuestion *)question withResult:(BOOL)result

    VRQuestion *nextQuestion = nil;

    if (result == YES) 
        nextQuestion = question.nextYesQuestion;
     else if (result == NO) 
        nextQuestion = question.nextNoQuestion;
    
    [self.qnaire pushAnswerResult:result forQuestion:question];

    // Handle no more questions
    if(nextQuestion) 
        [self prepareForQuestion:nextQuestion animated:YES];

     else 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Complete"
                                                            message:@"You completed the questionnaire"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [alertView show];
        [self.qnaire logAnswers];
    

我正在尝试将这些方法移至 InitialViewController ,但按钮什么也不做?

@implementation InitialViewController
- (IBAction)buttonPress:(UIButton *)sender 

    self.qnaire = [[VRQuestionnaire alloc] initWithFile:[[NSBundle mainBundle] pathForResource:@"set1"
                                                                                        ofType:@"json"]];
    //self.navController = (UINavigationController *)self.window.rootViewController;
    [self prepareForQuestion:self.qnaire.firstQuestion animated:NO];


提前致谢。

InitialViewController 按钮应调用 VRQuestionViewController(如下所示)

@interface VRQuestionViewController ()

@end

@implementation VRQuestionViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view.


- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];


    self.label.text = self.question.text;
    self.title = [self.question.identifier uppercaseString];


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


- (IBAction)yesPressed:(id)sender

    if (self.delegate != nil) 
        if ([self.delegate respondsToSelector:@selector(questionViewController:didAnswerQuestion:withResult:)]) 
            [self.delegate questionViewController:self didAnswerQuestion:self.question withResult:YES];
        
    


- (IBAction)noPressed:(id)sender

    if (self.delegate != nil) 
        if ([self.delegate respondsToSelector:@selector(questionViewController:didAnswerQuestion:withResult:)]) 
            [self.delegate questionViewController:self didAnswerQuestion:self.question withResult:NO];
        
    


@end

我当前的 AppDelegate:

#import <UIKit/UIKit.h>
#import "VRQuestionnaire.h"
#import "VRQuestionViewController.h"

@interface VRAppDelegate : UIResponder <UIApplicationDelegate>


@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) VRQuestionnaire *qnaire;


@end



#import "VRAppDelegate.h"
#import "VRQuestionViewController.h"

@implementation VRAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions


    self.qnaire = [[VRQuestionnaire alloc] initWithFile:[[NSBundle mainBundle] pathForResource:@"set1"
                                                                                        ofType:@"json"]];


    return YES;

和 InitialViewController:

#import "VRAppDelegate.h"
#import "VRQuestionViewController.h"

@implementation VRAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions


    self.qnaire = [[VRQuestionnaire alloc] initWithFile:[[NSBundle mainBundle] pathForResource:@"set1"
                                                                                        ofType:@"json"]];


    return YES;


#import "InitialViewController.h"

@interface InitialViewController ()

@end

@implementation InitialViewController
- (IBAction)buttonPress:(UIButton *)sender 

    self.qnaire = [[VRQuestionnaire alloc] initWithFile:[[NSBundle mainBundle] pathForResource:@"set1"
                                                                                        ofType:@"json"]];

    self.navController = (UINavigationController *)self.window.rootViewController;

    [self prepareForQuestion:self.qnaire.firstQuestion animated:NO];






/* Set up the question view controller with a question and push onto the nav stack
 */
- (void)prepareForQuestion:(VRQuestion *)question animated:(BOOL)animated;

    VRQuestionViewController *qvc = (VRQuestionViewController *)[self.navController.storyboard instantiateViewControllerWithIdentifier:@"QuestionViewController"];
    qvc.delegate = self;

    qvc.question = question;
    [self.navController pushViewController:qvc animated:animated];


/* Delegate that gets called every time a question is answered. This loads the next question and pushes it onto the nav stack.
 It also pushes a pointer to the question and result to a linked-list called firstAnswer->nextAnswer->nextAnswer, etc.

 When the next question returns nil we know we've finished as there are no more questions and log linked-list to console.
 */
- (void)questionViewController:(VRQuestionViewController *)controller didAnswerQuestion:(VRQuestion *)question withResult:(BOOL)result

    VRQuestion *nextQuestion = nil;

    if (result == YES) 
        nextQuestion = question.nextYesQuestion;
     else if (result == NO) 
        nextQuestion = question.nextNoQuestion;
    
    [self.qnaire pushAnswerResult:result forQuestion:question];

    // Handle no more questions
    if(nextQuestion) 
        [self prepareForQuestion:nextQuestion animated:YES];

     else 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Complete"
                                                            message:@"You completed the questionnaire"
                                                           delegate:nil
                                                  cancelButtonTitle:@"OK"
                                                  otherButtonTitles:nil];
        [alertView show];
        [self.qnaire logAnswers];
    




- (void)viewDidLoad 
    [super viewDidLoad];

    // Do any additional setup after loading the view from its nib.


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.

*/

@end

从导航控制器按住 CTRL 并拖动以创建 InitialViewController 根视图控制器。 按住 CTRL 键从按钮拖动到 VRQuestionViewController。

在模拟器中按下按钮 VRQuestionViewController 时显示没有问题或对 Y/N 的响应

对不起,如果这样,我会做一个真正的猪耳朵!

【问题讨论】:

为什么是视图控制器?看起来你应该有一个问题或问卷控制器。大概您当前的问题是 self.navController 为零? 完全 self.navController 是 nil .. 卡住了! InitialViewController 是导航控制器中的根视图控制器吗? 我有一个导航控制器标记为初始视图控制器 刚刚删除了这个,所以 InitialViewController 在情节提要中标记为初始视图控制器 - 虽然同样的问题 【参考方案1】:

有问题的代码似乎是 Github 上 https://github.com/rwarrender/DynamicQuestions 列出的示例代码

为了可读性,相当多的逻辑发生在应用程序委托中。应用程序委托初始化VRQuestionnaire 实例并设置问题。然后它在导航控制器上设置第一个问题视图控制器。每个VRQuestionViewController 都进行了配置,因此应用程序委托也是VRQuestionViewControllers 委托。回答完一个问题后,它会回调 questionViewController:didAnswerQuestion:withResult:,应用程序代表将结果推送到问卷的答案列表中,然后沿着问题树移动以显示下一个问题。

正如 Wain 所建议的,如果您想将其扩展为不止一个示例,您可能会将应用删除代码移动到控制器类中。您的初始视图控制器类有问题,因为所有内容都包装在导航控制器中,因此您的导航控制器应该是故事板中的初始视图控制器,InitialViewController 类作为导航控制器的根视图控制器。您可以通过右键单击从故事板中的导航控制器拖动到InitialViewController 来执行此操作。

希望有帮助!

【讨论】:

这有帮助,但我仍然在这里遗漏了一些东西 - 更新了我的问题 @Wain 我已按照您和@Electron 的建议将 InitialViewController 设置为根控制器。我发现 qvc 返回 nil,而在原始代码中它是 VRQuestionViewController 的一个实例。 - (void)prepareForQuestion:(VRQuestion *)question animated:(BOOL)animated; VRQuestionViewController *qvc = (VRQuestionViewController *)[self.navController.storyboard instantiateViewControllerWithIdentifier:@"QuestionViewController"]; qvc.delegate = self; qvc.question = question; //qvc nil [self.navController pushViewController:qvc animated:animated];

以上是关于如何将方法移出应用程序委托?的主要内容,如果未能解决你的问题,请参考以下文章

Rails:将逻辑移出视图

如何在 iphone 中使用应用程序委托方法

如何将应用程序委托添加回 mainwindow.xib

如何将值移出对象安全的特征对象?

如何将布尔值从应用程序委托传输到视图控制器?

如何检测 App 何时移入/移出 Suspended 状态?