Last active
January 26, 2022 01:19
-
-
Save TatsukiIshijima/d0e468950d19f70346048838eb14e4f9 to your computer and use it in GitHub Desktop.
iOSのPush通知実装サンプル
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AppDelegate.swift | |
// PushSample | |
// | |
import UIKit | |
import UserNotifications | |
@main | |
class AppDelegate: UIResponder, UIApplicationDelegate { | |
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { | |
UNUserNotificationCenter.current().delegate = self | |
// プッシュ通知の許可を要求 | |
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { (granted, error) in | |
if let error = error { | |
print("プッシュ通知許可要求エラー : \(error.localizedDescription)") | |
return | |
} | |
if !granted { | |
print("プッシュ通知が拒否されました。") | |
return | |
} | |
DispatchQueue.main.async { | |
// APNs への登録 | |
UIApplication.shared.registerForRemoteNotifications() | |
} | |
} | |
return true | |
} | |
} | |
extension AppDelegate: UNUserNotificationCenterDelegate { | |
// APNs 登録成功時に呼ばれる | |
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { | |
let token = deviceToken.map { String(format: "%.2hhx", $0) }.joined() | |
print("デバイストークン : \(token)") | |
} | |
// APNs 登録失敗時に呼ばれる | |
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { | |
print("APNs 登録に失敗しました : \(error.localizedDescription)") | |
} | |
// Push通知を受信した時(サイレントプッシュ) | |
// payload に "Content-available"=1 が設定されている、かつ | |
// BackgroundModes の RemoteNotification の設定も必要 | |
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { | |
guard let data = userInfo["data"] as? [String: Any], | |
let newTitle = data["newTitle"] as? String, | |
let newBody = data["newBody"] as? String else { | |
completionHandler(.noData) | |
return | |
} | |
// ローカル通知で表示するタイトルとメッセージを変更する | |
showLocalNotification(identifier: "SilentPush", title: newTitle, body: newBody) | |
completionHandler(.newData) | |
} | |
// フォアグラウンドで通知を受け取るために必要 | |
// フォアグラウンドで通知を受信した時 | |
// UNUserNotificationCenter.current().delegate = self も必須 | |
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { | |
completionHandler([.alert, .sound]) | |
} | |
// Push通知がタップされた時 | |
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { | |
let userInfo = response.notification.request.content.userInfo as NSDictionary | |
print("userNotificationCenter didReceive : userInfo=\(userInfo)") | |
completionHandler() | |
} | |
func showLocalNotification(identifier: String, title: String, body: String?) { | |
let content = UNMutableNotificationContent() | |
content.title = title | |
if let body = body { | |
content.body = body | |
} | |
content.sound = .default | |
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil) | |
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NotificationService.swift | |
// PushExtensionSample | |
// | |
import UserNotifications | |
class NotificationService: UNNotificationServiceExtension { | |
private var contentHandler: ((UNNotificationContent) -> Void)? | |
private var bestAttemptContent: UNMutableNotificationContent? | |
// プッシュ通知を受信した時に呼ばれる | |
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { | |
self.contentHandler = contentHandler | |
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) | |
guard let bestAttemptContent = bestAttemptContent else { | |
contentHandler(request.content) | |
return | |
} | |
guard let data = request.content.userInfo["data"] as? [String: Any], | |
let imageUrl = URL(string: data["imageUrl"] as? String ?? "") , | |
let newTitle = data["newTitle"] as? String, | |
let newBody = data["newBody"] as? String else { | |
contentHandler(bestAttemptContent) | |
return | |
} | |
// タイトルとボディを書き換え | |
bestAttemptContent.title = newTitle | |
bestAttemptContent.body = newBody | |
let downloadTask = URLSession.shared.downloadTask(with: imageUrl) { (url, _, _) in | |
guard let url = url else { | |
contentHandler(bestAttemptContent) | |
return | |
} | |
// tempに保存 | |
let fileName = imageUrl.lastPathComponent | |
let path = URL(fileURLWithPath: NSTemporaryDirectory().appending(fileName)) | |
do { | |
try FileManager.default.moveItem(at: url, to: path) | |
// 保存先のURLをプッシュ通知の表示領域に伝える | |
let attachment = try UNNotificationAttachment(identifier: fileName, url: path, options: nil) | |
bestAttemptContent.attachments = [attachment] | |
contentHandler(bestAttemptContent) | |
} catch { | |
contentHandler(bestAttemptContent) | |
} | |
} | |
downloadTask.resume() | |
} | |
// タイムアウト時に呼ばれる | |
override func serviceExtensionTimeWillExpire() { | |
if let contentHandler = contentHandler, | |
let bestAttemptContent = bestAttemptContent { | |
contentHandler(bestAttemptContent) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment