跳到内容

iOS 推送自定义

当 iOS 设备收到包含提醒的通知时,系统会分两个阶段显示提醒内容。首先,它会显示一个缩略横幅,其中包含通知的标题、副标题和两到四行的正文文本。如果用户按下缩略横幅,iOS 会显示完整的通知界面,包括任何与通知相关的操作。系统为缩略横幅提供界面,但您可以使用通知内容应用扩展程序自定义完整界面。

通知内容应用扩展程序管理一个显示自定义通知界面的视图控制器 (view controller)。此视图控制器可以补充或替换通知的默认系统界面。您可以使用视图控制器来:

  • 自定义项目的位置,包括提醒的标题、副标题和正文文本。
  • 为界面元素替换不同的字体或样式。
  • 显示应用特定数据——例如,存储在通知有效负载 (payload) 的应用特定键中的数据。
  • 包含自定义图像或品牌元素。

您的应用扩展程序必须使用立即可用的数据来配置其视图控制器,例如通知内容和应用扩展程序包 (bundle) 中存在的文件。如果您使用应用组 (app group) 在应用和应用扩展程序之间共享数据,您也可以使用在应用组中找到的任何文件。为确保您的通知能及时送达,请尽快配置视图。不要执行任何长时间运行的任务,例如尝试通过网络检索数据。

将通知内容应用扩展程序添加到您的项目中

Anchor link to

要将通知内容应用扩展程序添加到您的 iOS 应用中:

  1. 在 Xcode 中选择 File > New > Target
  2. 从 iOS Application Extension 中选择 Notification Content Extension
  3. 点击 Next
  4. 为您的应用扩展程序提供一个名称
  5. 点击 Finish

向您的视图控制器添加视图

Anchor link to

Xcode 提供的模板包含一个故事板 (storyboard) 和一个视图控制器 (view controller) 供您配置。通过向视图控制器添加视图来构建您的自定义通知界面。例如,使用标签 (labels) 来显示通知的标题、副标题和正文文本。您还可以添加图像视图 (image views) 和显示非交互式内容的视图。您无需为视图提供任何初始内容。

在 iOS 12 及更高版本中,您可以添加交互式控件(例如,按钮或开关)。有关更多信息,请参阅支持交互式控件。

配置您的视图控制器

Anchor link to

使用视图控制器的 didReceive(_:) 方法来更新其标签和其他视图。通知有效负载 (payload) 包含配置视图控制器时要使用的数据。您也可以使用来自应用扩展程序其他文件的数据。清单 1 展示了此方法的一个版本,它从通知有效负载中检索标题和正文文本,并将字符串分配给两个 UILabel 控件,这些控件作为出口 (outlets) 存储在视图控制器上。

// Configuring the notification interface at runtime
func didReceive(_ notification: UNNotification) {
self.bodyText?.text = notification.request.content.body
self.headlineText?.text = notification.request.content.title
}

如果在您的视图控制器已经可见时有第二条通知到达,系统会再次调用 didReceive(_:) 方法,并传入新的通知有效负载。

支持交互式控件

Anchor link to

在 iOS 12 及更高版本中,您可以在自定义通知中启用用户交互。这允许您向自定义界面添加交互式控件,例如按钮和开关。

要启用用户交互:

  1. 打开您的通知内容扩展程序的 info.plist 文件。
  2. UNNotificationExtensionUserInteractionEnabled 键添加到您的扩展程序属性中。为其指定一个布尔值,设置为 YES
在通知扩展程序的 info.plist 文件中启用用户交互

将 Apple Pay 添加到您的推送通知扩展程序中(示例视图)

Anchor link to

在推送通知扩展程序中使用 Apple Pay 按钮的代码块示例

Anchor link to
import UIKit
import Foundation
import UserNotifications
import UserNotificationsUI
import PassKit
class NotificationViewController: UIViewController, UNNotificationContentExtension, PKPaymentAuthorizationViewControllerDelegate {
func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
controller.dismiss(animated: true, completion: nil)
}
@IBOutlet weak var buyWithApplePayButton: UIButton!
@IBOutlet weak var containerView: UIView!
@IBOutlet weak var payInAppButton: UIButton!
@IBOutlet weak var segmentCustom: UISegmentedControl!
private var amount: NSDecimalNumber = 0;
override func viewDidLoad() {
super.viewDidLoad()
buttonCustomisation()
amount = NSDecimalNumber.init(value: 5)
}
func buttonCustomisation () {
self.buyWithApplePayButton.layer.masksToBounds = true
self.buyWithApplePayButton.layer.cornerRadius = 10
self.payInAppButton.layer.masksToBounds = true
self.payInAppButton.layer.cornerRadius = 10
self.containerView.layer.borderColor = UIColor.gray.cgColor
self.containerView.layer.borderWidth = 0.7
self.containerView.layer.masksToBounds = true
self.containerView.layer.cornerRadius = 20
}
func didReceive(_ notification: UNNotification) {
// Configuring the notification interface at runtime
}
@IBAction func buyWithApplePayAction(_ sender: Any) {
let request = PKPaymentRequest()
request.merchantIdentifier = "merchant.com.sample.ApplePayAction"
request.supportedNetworks = [PKPaymentNetwork.visa, PKPaymentNetwork.masterCard, PKPaymentNetwork.amex]
request.merchantCapabilities = PKMerchantCapability.capability3DS
request.countryCode = "US"
request.currencyCode = "USD"
request.paymentSummaryItems = [
PKPaymentSummaryItem(label: "Some Product", amount: amount)
]
let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request)
applePayController?.delegate = self
self.present(applePayController!, animated: true, completion: nil)
}
@IBAction func payInAppButtonAction(_ sender: Any) {
print("pay in app button tapped")
}
@IBAction func segmentAction(_ sender: Any) {
switch segmentCustom.selectedSegmentIndex {
case 0:
amount = NSDecimalNumber.init(value: 5)
break
case 1:
amount = NSDecimalNumber.init(value: 10)
break
case 2:
amount = NSDecimalNumber.init(value: 20)
break
default:
amount = NSDecimalNumber.init(value: 5)
break
}
}
}