Badge label not appearing in Monterey 12.0.1

Using the Lazarus IDE and Free Pascal the following code works in previous macOS versions, but not in Monterey:

procedure TForm1.FormActivate(Sender: TObject);
begin
  NSApp := NSApplication.sharedApplication;
end; 

procedure TForm1.Button1Click(Sender: TObject);
begin
  NSApp.dockTile.setBadgeLabel(NSStr('1'));
end;   

Any ideas why it fails in Monterey? There are no related errors in the system console log.

Replies

Upgrading to Monterey 12.1 made no difference. I also notice the App Store dock icon no longer shows a badge for apps to be updated, but the System Preferences dock icon does show when there's an system software update.

To show badge label, application should be authorized to do it. You should call:

UNUserNotificationCenter requestAuthorizationWithOptions with UNAuthorizationOptionBadge

on applicationDidFinishLaunching before assigning any badge.

After

completionHandler

is done, you became able to assign badges and them should appear.

Curiously, with Monterey and subsequent macOS versions up to and including Sonoma, the Lazarus GUI program worked on some machines but not others for no reason I can determine (I have a stable of Mac minis :)

Anyway, while the Lazarus GUI version has this unreliability issue from Monterey onwards, my pure Pascal program below does not. It works on all machines and all macOS versions.

program badger;

{$mode objfpc}{$H+}
{$modeswitch objectivec1}

uses
CocoaAll;

type
  { TMyDelegate }
  TMyDelegate = objcclass(NSObject)
  public
    procedure BadgeButtonClick(sender :  id); message 'BadgeButtonClick:';
    procedure UnBadgeButtonClick(sender :  id); message 'UnBadgeButtonClick:';
  end;

var
   appName    : NSString;
   window     : NSWindow;
   myBadgeButton   : NSButton;
   myUnBadgeButton : NSButton;
   myDelegate : TMyDelegate;

procedure TMyDelegate.BadgeButtonClick(sender :  id);
begin
   NSApp.dockTile.setBadgeLabel(NSStr('12'));
end;

procedure TMyDelegate.UnBadgeButtonClick(sender :  id);
begin
   NSApp.dockTile.setBadgeLabel(Nil);
end;

begin
   // app and window creation
   NSApp := NSApplication.sharedApplication;
   NSApp.setActivationPolicy(NSApplicationActivationPolicyRegular);
   appName := NSStr('Badger');
   window := NSWindow.alloc.initWithContentRect_styleMask_backing_defer(NSMakeRect(0, 0, 200, 200),
                NSTitledWindowMask or NSClosableWindowMask or NSMiniaturizableWindowMask,
                NSBackingStoreBuffered, False);
   myDelegate := TMyDelegate.alloc.init;

   // badge button
   myBadgeButton := NSButton.alloc.initWithFrame(NSMakeRect(50, 100, 100, 50));
   window.contentView.addSubview(myBadgeButton);
   myBadgeButton.setTitle(NSSTR('Badge'));
   myBadgeButton.setButtonType(NSMomentaryLightButton);
   myBadgeButton.setBezelStyle(NSRoundedBezelStyle);

   // unbadge button
   myUnBadgeButton := NSButton.alloc.initWithFrame(NSMakeRect(50, 60, 100, 50));
   window.contentView.addSubview(myUnBadgeButton);
   myUnBadgeButton.setTitle(NSSTR('UnBadge'));
   myUnBadgeButton.setButtonType(NSMomentaryLightButton);
   myUnBadgeButton.setBezelStyle(NSRoundedBezelStyle);

   // badge button event handler
   myBadgeButton.setTarget(myDelegate);
   myBadgeButton.setAction(ObjCSelector(myDelegate.BadgeButtonClick));

   // unbadge button event handler
   myUnBadgeButton.setTarget(myDelegate);
   myUnBadgeButton.setAction(ObjCSelector(myDelegate.UnBadgeButtonClick));

   // Window showing and app running
   window.center;
   window.setTitle(appName);
   window.makeKeyAndOrderFront(Nil);
   NSApp.activateIgnoringOtherApps(True);
   NSApp.run;
end.

As to the UNUserNotificationCenter, this is currently not available in Lazarus (due to somewhat outdated Pascalised Cocoa headers), but thanks for responding!