# Error
class Notification(NSObject):
objc.BadPrototypeError: Objective-C expects 1 arguments, Python argument has 2 arguments for <unbound selector send of Notification at 0x10e410180>
现在进入代码:
# vscode may show the error: "No name '...' in module 'Foundation'; you can ignore it"
from Foundation import NSUserNotification, NSUserNotificationCenter, NSObject, NSDate
from PyObjCTools import AppHelper
def notify(
title='Notification',
subtitle=None, text=None,
delay=0,
action_button_title=None,
action_button_callback=None,
other_button_title=None,
other_button_callback=None,
reply_placeholder=None,
reply_callback=None
):
class Notification(NSObject):
def send(self):
notif = NSUserNotification.alloc().init()
if title is not None:
notif.setTitle_(title)
if subtitle is not None:
notif.setSubtitle_(subtitle)
if text is not None:
notif.setInformativeText_(text)
# notification buttons (main action button and other button)
if action_button_title:
notif.setActionButtonTitle_(action_button_title)
notif.set_showsButtons_(True)
if other_button_title:
notif.setOtherButtonTitle_(other_button_title)
notif.set_showsButtons_(True)
# reply button
if reply_callback:
notif.setHasReplyButton_(True)
if reply_placeholder:
notif.setResponsePlaceholder_(reply_placeholder)
NSUserNotificationCenter.defaultUserNotificationCenter().setDelegate_(self)
# setting delivery date as current date + delay (in seconds)
notif.setDeliveryDate_(NSDate.dateWithTimeInterval_sinceDate_(delay, NSDate.date()))
# schedule the notification send
NSUserNotificationCenter.defaultUserNotificationCenter().scheduleNotification_(notif)
# on if any of the callbacks are provided, start the event loop (this will keep the program from stopping)
if action_button_callback or other_button_callback or reply_callback:
print('started')
AppHelper.runConsoleEventLoop()
def userNotificationCenter_didDeliverNotification_(self, center, notif):
print('delivered notification')
def userNotificationCenter_didActivateNotification_(self, center, notif):
print('did activate')
response = notif.response()
if notif.activationType() == 1:
# user clicked on the notification (not on a button)
# don't stop event loop because the other buttons can still be pressed
pass
elif notif.activationType() == 2:
# user clicked on the action button
action_button_callback()
AppHelper.stopEventLoop()
elif notif.activationType() == 3:
# user clicked on the reply button
reply_text = response.string()
reply_callback(reply_text)
AppHelper.stopEventLoop()
# create the new notification
new_notif = Notification.alloc().init()
# return notification
return new_notif
def main():
n = notify(
title='Notification',
delay=0,
action_button_title='Action',
action_button_callback=lambda: print('Action'),
# other_button_title='Other',
# other_button_callback=lambda: print('Other'),
reply_placeholder='Enter your reply please',
reply_callback=lambda reply: print('Replied: ', reply),
)
n.send()
if __name__ == '__main__':
main()
def userNotificationCenter_didActivateNotification_(self, center, notif):
print('did activate')
response = notif.response()
if notif.activationType() == 1:
# user clicked on the notification (not on a button)
# don't stop event loop because the other buttons can still be pressed
pass
elif notif.activationType() == 2:
# user clicked on the action button
# action button callback
action_button_callback()
AppHelper.stopEventLoop()
elif notif.activationType() == 3:
# user clicked on the reply button
reply_text = response.string()
# reply button callback
reply_callback(reply_text)
AppHelper.stopEventLoop()
编辑(2020年6月27日):我创建了一个包,它具有在Mac OShere上显示通知的功能。它将使用PyObjC创建和显示通知。如果它因任何原因无法工作,它将返回到带有
osascript
的AppleScript通知。我做了一些测试,发现PyObjC通知在某些设备上可以工作,但在某些设备上不能工作回答:
我也一直在寻找这个答案,所以我想与大家分享我的发现:
您会注意到的第一件事是函数
notify()
定义了一个类,然后返回它的一个实例。您可能想知道为什么不能直接调用Notification.send(params)
。我试过了,但PyObjC出现了一个错误,不幸的是我无法修复:现在进入代码:
解释
notify()
函数接受相当多的参数(它们是自解释的)。delay
是通知出现的秒数。请注意,如果设置的延迟比程序的执行时间长,则将在程序执行后发送通知您将看到按钮参数。有三种类型的按钮:
所有这些
if
语句都适当地设置了按钮,并且不言自明。例如,如果未提供其他按钮的参数,则不会显示其他按钮您会注意到,如果有按钮,我们将启动控制台事件循环:
这是Python Objective-C的一部分。这不是一个很好的解释,但它基本上保持了程序的“开”(我希望有人能给出更好的解释)
基本上,如果您指定需要一个按钮,程序将继续“打开”,直到
AppHelper.stopEventLoop()
(稍后将详细介绍这一点)现在有一些“钩子”功能:
userNotificationCenter_didDeliverNotification_(self, notification_center, notification)
:在传递通知时调用userNotificationCenter_didActivateNotification_(self, notification_center, notification)
:当用户与通知交互时调用(单击、单击操作按钮或回复)(documentation)当然还有更多,但不幸的是,我不认为撤销或忽视通知有什么好处
使用
userNotificationCenter_didActivateNotification_
,我们可以定义一些回调:操作类型有不同的激活类型。还可以检索回复操作中的文本,如图所示
您还将注意到结尾处的
AppHelper.stopEventLoop()
。这意味着“结束”程序的执行,因为通知已由用户处理现在,让我们解决这个解决方案的所有问题
问题
AppHelper.stopEventLoop()
李>AppHelper.stopEventLoop()
是在交互之后运行的,所以不可能通过回调发送多个通知,因为程序将在与第一个通知交互之后停止执行李>我还应该使用这个解决方案吗
如果需要回调通知,可能不应该,因为我已经解决了这些问题
如果您只想向显示通知,请提醒用户是的,是的
其他解决方案
PYNC是terminal-notifier的包装器。然而,这两家公司的最后一次承诺都是在2018年Alerter似乎是终端通知程序的继承者,但没有Python包装器
您也可以尝试运行applescript发送通知,但不能设置回调,也不能更改图标
我希望这个答案对你有所帮助。我还试图找出如何在Mac OS上可靠地通过回调发送通知。我已经知道了如何发送通知,但问题在于回调
相关问题 更多 >
编程相关推荐