【问题标题】:Call a function in AppDelegate?在 AppDelegate 中调用函数?
【发布时间】:2011-11-22 20:18:46
【问题描述】:

按照UITextField Example in Cocos2d 的解决方案(实际上是最高投票的答案),我设法做到了,除了这条线

[[[UIApplication sharedApplication] delegate] specifyStartLevel];

我已将它放在我的场景中,我收到以下警告:

找不到实例方法“-specifyStartLevel”(返回类型默认为“id”)

这是为什么呢?我显然在我的 AppDelegate 的标头和实现中定义了 -specifyStartLevel...


编辑specifyStartLevel

的声明
#import <UIKit/UIKit.h>

@class RootViewController;

@interface AppDelegate : NSObject <UIApplicationDelegate,UITextFieldDelegate> {
    UIWindow            *window;
    UITextField *levelEntryTextField;
    RootViewController  *viewController;
}
- (void)specifyStartLevel;
@property (nonatomic, retain) UIWindow *window;

@end

及实施:

- (void)specifyStartLevel
{
    [levelEntryTextField setText:@""];
    [window addSubview:levelEntryTextField];
    [levelEntryTextField becomeFirstResponder];    
}

【问题讨论】:

  • 请提供specifyStartLevel的声明代码。

标签: objective-c cocos2d-iphone


【解决方案1】:

现在,您的班级对您的委托方法一无所知。您需要将您的委托导入您的实现,而不是您的接口(以避免循环导入)。

例如,

#import "AppDelegate.h"

然后您应该将嵌套方法调用中返回的委托转换为您的委托类型。例如:

[(AppDelegate *)[[UIApplication sharedApplication] delegate] specifyStartLevel];

【讨论】:

  • 谢谢 - 没有更多的警告。但是,当我从场景中调用它时,键盘没有出现。然而,如果我直接在 AppDelegate 中调用该函数,它确实可以。有想法吗?
  • 这很奇怪。请设置断点或在specifyStartLevel 函数中添加日志,以查看从子类中调用它时是否运行。
  • 看来它毕竟被调用了。但是,键盘似乎根本不可见。
  • 这很奇怪。我只是在这里针对您的问题创建一个新问题,而不是试图在这里解决。
  • 啊! 运行场景后,我正在创建 UITextField。现场正试图从init方法打开键盘...谢谢先生。
【解决方案2】:
  1. AppDelegate.h 文件中添加您的方法,例如:

    - (void)Welcome
    
  2. 实现AppDelegate.m文件中的方法如:

     - (void)Welcome
     {
         NSLog(@"Welcome")
    
     }
    
  3. 在方法中设置UIApplication委托,例如:

    AppDelegate *appDelegate=[UIApplication sharedApplication] delegate];
    
    [appDelegate Welcome];
    

【讨论】:

    【解决方案3】:

    -[UIApplication delegate] 返回一个id&lt;UIApplicationDelegate&gt; 类型的对象,因此编译器只知道该类型的对象响应的方法,即使您的自定义委托响应specifyStartLevel。您可以忽略警告,也可以强制转换 -[UIApplication delegate] 的返回值:

    [(YourCustomAppDelegate *) [[UIApplication sharedApplication] delegate] specifyStartLevel];
    

    【讨论】:

    • 强制转换优于忽略警告。警告被称为警告是有原因的,如果您养成忽略它们的坏习惯,它可能会导致细微的错误。
    • @Paul.s:没错,但在这种情况下,忽略它绝对是安全的。
    • 是的,除非您更改方法签名并忘记在代码中的其他地方更新,否则它是完全无辜的。如果您删除了原始警告,那么您会得到一个很好的新警告来告诉您这一点。如果我按照自己的方式进行编译,我将始终使用-Werror
    • @Paul.s:使用动态类型语言的缺点之一。单元测试实际上应该防止此类错误。但是,如果你愿意的话,你可以施放,两全其美。
    【解决方案4】:

    您需要将 AppDelegate 导入到您使用的 .m 文件中

    [[[UIApplication sharedApplication] delegate] specifyStartLevel];
    

    我喜欢用一个给我快捷方式的标题导入它。

    GlobalData.h
    
    #import "AppDelegate.h"
    #define APPDELEGATE (AppDelegate *)[[UIApplication sharedApplication] delegate]
    

    然后当我在任何课程中使用它时,我只是

    #import "GlobalData.h"
    
    // to gain access to the delegate
    AppDelegate * appDelegate = APPDELEGATE;
    

    我使用这种方法是因为我可以将更多的#define 存储到一些全局常量中 (即 soundFXVolume - #define SOUND_FX_V 0.6

    【讨论】:

    • +1 表示宏。通常我会说它们是邪恶的,但在这种情况下它很有用。
    猜你喜欢
    • 1970-01-01
    • 2020-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    相关资源
    最近更新 更多