【问题标题】:Triggering delegate method in ViewController from Appdelegate从 Appdelegate 触发 ViewController 中的委托方法
【发布时间】:2014-01-17 13:20:44
【问题描述】:

我正在尝试使用 AppDelegate 通过和 NSTimer 在视图控制器中触发委托方法。所以在AppDelegate中,我基本上有:

AppDelegate.h

@protocol TestDelegate <NSObject>

-(void)testFunction:(NSString *)testString;

@end

@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) id<TestDelegate> testDelegate;
...
@end

AppDelegate.m

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

    [self.window makeKeyAndVisible];


    self.timer = [NSTimer scheduledTimerWithTimeInterval:10.0
                                                  target:self
                                                selector:@selector(trigger:)
                                                userInfo:nil
                                                 repeats:YES];
    return YES;
}

-(void)trigger:(id)sender {
   [self.testDelegate testFunction:self];
}

在我的视图控制器中,我有:

ViewController.h

@interface ViewController : UIViewController <TestDelegate>
    @property (nonatomic, strong) AppDelegate *appDelegate;
@end

ViewController.m

@implementation ViewController
   ...
   -(void)viewDidLoad {
       self.appDelegate = [[UIApplication sharedApplication] delegate];
       self.appDelegate.testDelegate = self;
   }

   -(void)testfunction:(NSString *)testString {
       NSLog(@"%@", testString);
   }
@end

当我在我的应用程序中加载 ViewController 时,没有任何反应?我知道 NSTimer 已成功触发,但未触发委托方法。

【问题讨论】:

  • 你在哪里给 testDelegate 赋值?
  • 在我的 appdelegate.h 中,我有 @property (strong, nonatomic) id testDelegate;
  • 哦,我明白你的意思了......
  • 在这个例子中我可以在哪里分配代理?
  • 只要有可能 - 创建 ViewController 并将其分配为委托

标签: ios objective-c


【解决方案1】:

你的函数声明是:

-(void)testFunction:(NSString *)testString;

但你称它为:

[self.testDelegate testFunction:self];

所以您将self 发送到一个期望指向NSString 的参数,这显然是不正确的。

另外,我会像这样使用 GCD,而不是使用计时器:

double delayInSeconds = 10.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));

dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    if [self.testDelegate respondsToSelector:@selector(testFunction:)] {
        [self.testDelegate testFunction:@"Test String"];
    }
});

【讨论】:

  • 感谢您的回答,只是好奇,因为我还没有得到简明的答案,但为什么 GCD 优于 NSTimer?使用 NSTimer 的缺点是什么?
  • 另一个问题是既然定义了协议,为什么原始代码编译?
  • 在这种情况下我更喜欢使用 GCD,因为我只触发一次。这样我就没有另一个属性来保存计时器,而且我也不必设置所有代码来创建计时器。另外,请考虑您希望计时器做一件事的情况。你不需要写一个方法作为回调,你可以在块中写代码,这样你就可以直接看到定时器会运行什么。
  • 我看到了,但是如果有一个定义的协议 id 编译器应该注意到你发送 self 到 testFunction 期望一个 NSString
  • 也许确实如此。不过,并不是每个人都注意警告。虽然我强烈建议构建 0 个警告 - 我们是什么,Windows 程序员?
【解决方案2】:

用途:

[[UIApplication sharedApplication].testDelegate = self;

而不是所有这些:

self.appDelegate = [[UIApplication sharedApplication] delegate];
self.appDelegate.testDelegate = self;

【讨论】:

    【解决方案3】:

    您在哪里指定您的 VC 作为代表?是您的 VC 在初始化/视图期间自行分配的吗?如果你不这样做,我会在 ViewDidLoad 中分配它。

    - (void)viewDidLoad
    {
         [super viewDidLoad];
         [[UIApplication sharedApplication]delegate].testDelegate = self;
    }
    

    此外,您可能希望将 AppDelegate 中的属性设置为弱而不是强,以避免在/如果它被解除时保留 VC。

    【讨论】:

    • 我刚刚将这个添加到viewcontroller viewdidload,但由于某种原因它仍然无法正常工作?
    • 这应该是个问题
    【解决方案4】:

    点赞

    if(!testDelegate) {
       [self.testDelegate testFunction:self];
    }
    

    如果您的控制器在您的导航控制器中,则循环并找到您的控制器活动对象并分配委托。

    但我会推荐使用 LocalNotification 的这种功能

    【讨论】:

      猜你喜欢
      • 2018-05-15
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      相关资源
      最近更新 更多