【问题标题】:Check a condition in the background every ten seconds and send notification每十秒在后台检查一次条件并发送通知
【发布时间】:2011-05-17 13:39:51
【问题描述】:

我正在开发适用于 Mac OS X 的应用程序。我的应用程序每十秒检查一次,如果条件为真,应用程序会发送 Growl 通知。

我已经编写了 Growl 通知和检查代码。我只需要知道如何让这种检查每十秒重复一次,并且每次如果为真则在后台发送通知。

请写出准确的代码,因为我是 Objective-C 的新手。谢谢 :D

-------------------编辑--------------- ---------------------

目前我正在使用这个:

//  MyApp_AppDelegate.m

#import "MyApp_AppDelegate.h"

@implementation MyApp_AppDelegate

- (void)awakeFromNib {
    return;
}


-(void)applicationDidFinishLaunching:(NSNotification*)aNotification {

    // grwol:
    NSBundle *myBundle = [NSBundle bundleForClass:[MyApp_AppDelegate class]];
    NSString *growlPath = [[myBundle privateFrameworksPath] stringByAppendingPathComponent:@"Growl-WithInstaller.framework"];
    NSBundle *growlBundle = [NSBundle bundleWithPath:growlPath];

    #include <unistd.h>

    int x = 0;
    int l = 10; // time/repeats
    int t = 10; //seconds
    while ( x <= l ) {

        // more code here only to determine sendgrowl value...

        if(sendgrowl) {
            if (growlBundle && [growlBundle load]) {
                // more code to sends growl
            } else {
                NSLog(@"ERROR: Could not load Growl.framework");
            }
        }

        // do other stuff that doesn't matter...

        // wait:
        sleep(t);

        x++;
    }
}

/* Dealloc method */
- (void) dealloc { 
    [super dealloc]; 
}

@end

【问题讨论】:

  • 永远不要在应用程序主线程上运行的方法中使用sleep()。整个 UI 将冻结这段时间。
  • 概括:永远不要使用sleep()
  • 还有;鉴于您为回答答案而提出的问题的基本性质,我建议您阅读 Objective-C 和 Cocoa 入门指南。他们会很有帮助。
  • 此外,尽可能不要轮询事物,即使是在计时器上。最好使用不同的机制(例如 kqueue),这样您的应用程序就不会消耗不必要的 CPU 周期,或者(更糟糕的是)无意中使机器无法进入睡眠状态。

标签: objective-c cocoa macos background


【解决方案1】:

您正在寻找的确切代码可以在这里找到: Time Programming Topics

【讨论】:

  • 谢谢,但正如我所说,我是 obj-c 的新手,那里一半以上的代码我不明白,你不能只给我我需要的东西吗...
  • 标题为“Scheduled Timers”的部分是您需要阅读的所有内容。我知道阅读文档可能会让人感到困惑,但是一旦您学会浏览它们,找到问题的答案就会变得容易得多。
  • 那么您需要向我们展示您的尝试。否则我们不可能提供帮助。
  • @sosborn:用我正在使用的东西编辑了这个问题......我希望每 5 秒重复一次代码( t )......
  • Jano 和 JeremyP 发布了您需要的内容,请接受其中之一作为答案。如果您返回并查看我建议阅读的部分,您会看到除了方法名称之外看起来完全相同的代码。使用他们发布的代码,然后返回并再次阅读文档的该部分。现在您有机会在您的应用中使用它应该更有意义。
【解决方案2】:
-(void) sendGrowl { } // your growl method

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self 
                  selector:@selector(sendGrowl) userInfo:nil repeats:YES]; 

当你完成定时器调用[timer invalidate]。粘贴到 XCode 并 alt+单击它以阅读文档。

【讨论】:

    【解决方案3】:

    要安排计时器每 10 秒运行一次,您需要这样做:

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 10.0
                                                      target: someObject 
                                                    selector: @selector(fire:)
                                                    userInfo: someParameter
                                                     repeats: YES];
    

    这将创建一个计时器并将其置于运行循环中,使其每 10 秒触发一次。当它触发时,相当于如下的方法调用:

    [someObject fire: someParameter];
    

    您可以将 nil 作为 someParameter 传递,在这种情况下,您的选择器不需要带参数,即它可以是 -fire 而不是 -fire:

    要停止计时器,只需发送invalidate 消息即可。

    [timer invalidate];
    

    计时器需要运行循环才能工作。如果您在应用程序的主线程上运行它,这很好,因为主线程已经有一个运行循环(它处理 UI 事件并将它们传递给您的操作)。如果您希望计时器在不同的线程上触发,则必须在该不同的线程上创建并运行运行循环。这有点高级,所以如果您是 Objective-C 的新手,请暂时避免使用它。


    编辑

    看到您要执行的操作后,安排计时器的第一段代码需要替换整个 while 循环。 -fire 方法看起来像:

    -fire
    {
        // code here only to determine sendgrowl value...
    
        if(sendgrowl) 
        {
            if (growlBundle && [growlBundle load]) 
            {
                // more code to sends growl
            }
            else 
            {
                NSLog(@"ERROR: Could not load Growl.framework");
            }
        }
        // do other stuff that doesn't matter...
    }
    

    【讨论】:

    • 最后一个问题:我应该把NSBundle *myBundle = [NSBundle bundleForClass:[MyApp_AppDelegate class]]; NSString *growlPath = [[myBundle privateFrameworksPath] stringByAppendingPathComponent:@"Growl-WithInstaller.framework"]; NSBundle *growlBundle = [NSBundle bundleWithPath:growlPath];NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 10.0 target: someObject selector: @selector(fire:) userInfo: someParameter repeats: YES];[someObject fire: someParameter][timer invalidate] 放在哪里...非常感谢:)
    • 捆绑的东西留在原处。调度计时器应该替换整个 while 循环。
    • NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval: 10.0 target: someObject selector: @selector(fire:) userInfo: someParameter repeats: YES]; 在捆绑的东西之后?
    • @Andy:是的,您可以考虑进行测试,以便在发现 Growl 捆绑包不存在时根本不安排计时器(而不是在每次触发计时器时检查)。
    猜你喜欢
    • 1970-01-01
    • 2019-04-23
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-15
    • 1970-01-01
    相关资源
    最近更新 更多