1

I've to develop a tiny program that send a local notification in on my Mac. This notification must be sent every 30 sec, so I create a command line tool with Xcode and I choose to develop in Objective-C. Xcode shows me the main.m file, in which I wrote the following code:

main.m

#import <Foundation/Foundation.h>
#import "Notification.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Notification *notification = [[Notification alloc]init];
        [notification startNotification];
    }
    return 0;
}

where Notification it's a class in which I start a timer and I send the notification, the code is:

Notification.h

@interface Notification : NSObject <NSUserNotificationCenterDelegate>

- (void) startNotification;

@end

Notification.m

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "Notification.h"

@implementation Notification : NSObject

- (void) startNotification {
    NSTimer *timer = [[NSTimer alloc]init];
    if (timer == nil) {
        timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:@selector(sendNotification) userInfo:nil repeats:YES];
    }
}

- (void)sendNotification {
    NSUserNotification *notification = [[NSUserNotification alloc]init];
    notification.title = @"Prova";
    notification.informativeText = @"Ciao Salame";
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications];

    NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
    [center scheduleNotification:notification];
    [center setDelegate:self];
}

- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
    NSAlert *alert = [[NSAlert alloc]init];
    [alert addButtonWithTitle:@"OK"];
    [alert setMessageText:notification.title];
    [alert setInformativeText:notification.informativeText];
    [alert setAlertStyle:NSWarningAlertStyle];
    [alert runModal];
    [center removeDeliveredNotification:notification];
}

@end

when I run the app it doesn't calls the selector method and it finish to run, what's wrong in my little program? Can you help me to fix it?

Thank you

AppleScript

I create a tiny AppleScript and it's working quite well, the code I used is the following:

on idle

    display notification "Lorem ipsum dolor sit amet" with title "Title"

    return 30

end idle

then I created an app from this script and it will be execute at the startup of the system and it's sending me a notification every 30 sec. I'm not sure if it's the right way to do that, but it's working...

LOOK FROM HERE

Objective-C

I've try to update my code as follow:

Notification.m

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "Notification.h"

@implementation Notification : NSObject

- (void) startNotification {
    NSUserNotification *notification = [[NSUserNotification alloc]init];
    notification.title = @"Prova";
    notification.informativeText = @"Ciao Salame";
    notification.soundName = NSUserNotificationDefaultSoundName;

    [[NSUserNotificationCenter defaultUserNotificationCenter] deliveredNotifications];

    NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter];
    [center scheduleNotification:notification];
    [center setDelegate:self];
    sleep(30);

}

- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification {
    NSAlert *alert = [[NSAlert alloc]init];
    [alert addButtonWithTitle:@"OK"];
    [alert setMessageText:notification.title];
    [alert setInformativeText:notification.informativeText];
    [alert setAlertStyle:NSWarningAlertStyle];
    [alert runModal];
    [center removeDeliveredNotification:notification];
}

but it doesn't send me the notification...

lucgian841
  • 1,830
  • 5
  • 34
  • 57

1 Answers1

0

The reason is, that your app directly returns after instantiating Notification. Just calling startNotification does not prevent the app from returning. Probably you want to let it run inside a thread in the background.

Sebastian
  • 8,046
  • 2
  • 34
  • 58
  • Ok, so can you help me to find a solution to do this? Or I should use an AppleScript? – lucgian841 Jan 14 '15 at 09:55
  • I think you want something like a daemon which are processes running in the background, e.g. have a look at [Creating Launch Daemons and Agents](https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html). Another (quick) solution would be to run a loop and let the process sleep every 30s. – Sebastian Jan 14 '15 at 09:58
  • That's what I will do and I know how to start a daemon, just I'm not understanding how to write code to do that... – lucgian841 Jan 14 '15 at 10:00
  • I think you first have to ensure, that your program does not quits directly. I.e. for now use `sleep(30)` inside a loop and once it returns it'll send the notification (so, no more `NSTimer`). Once this works you could use a background thread which performs this task, so that you have the ability to properly interact with the app. – Sebastian Jan 14 '15 at 10:21
  • I updated my question, try to have a look about it, I'm not sure it's the right way, but it's working – lucgian841 Jan 14 '15 at 10:27
  • I think that's a valid approach :) – Sebastian Jan 14 '15 at 10:35
  • you think that's better to use AppleScript or Objective-C? – lucgian841 Jan 14 '15 at 10:36
  • Depends on your long-term goal. If it is only for you, probably use that AppleScript. If you want to publish something somewhere, make it a daemon or if it is part of an app, it may be sufficient to run it as background task. – Sebastian Jan 14 '15 at 11:02
  • I need that to notify something to an app, but the Objective-C code doesn't work instead of the AppleScript code. What's wrong in my Objective-C code? Why it doesn't shows me the notification? I created a demo app in which I press a button and I send the notification with the same code and it's working, why if I use this solution it doesn't work? Can you help me please? – lucgian841 Jan 14 '15 at 11:07
  • As I said before: your app directly terminates, because adding a timer does not prevent it from exiting. So, do not use a timer but use `sleep` and a loop. Then it will run until you quit it by hitting Ctrl+C. – Sebastian Jan 14 '15 at 11:08
  • As I told you a few comments ago, in the second version of my Objective-C app (the new code with sleep begin from "LOOK FROM HERE" in my question) I set a `sleep(30);` after sending notification but it doesn't send the notification. I followed your suggestion. But my issue is that if I run the app it execute the notification code, but it doesn't shows me nothing... Why is that? – lucgian841 Jan 14 '15 at 11:14
  • I think its rather `deliverNotification` instead of `scheduleNotification`. And I think it also requires a delegate, but I'm not sure. Maybe [Send notification to Mountain lion notification center](http://stackoverflow.com/questions/11814903/send-notification-to-mountain-lion-notification-center) helps. – Sebastian Jan 14 '15 at 11:20
  • Then, I don't know. Maybe it has something to do with permissions. Maybe there is a good example somewhere. – Sebastian Jan 14 '15 at 11:35
  • It was a very difficult idiot issue! I found here something: http://stackoverflow.com/questions/11712535/mac-mountain-lion-send-notification-from-cli-app it doesn't work because we doesn't set the `NSBundle`on this there are written how to send notification by command line tool... I hope it will be useful for you. Thank you for helping me :) – lucgian841 Jan 14 '15 at 11:44
  • Sure! Glad you figured it out ... there are no idiotic issues ;) – Sebastian Jan 14 '15 at 11:46