2017-06-20 67 views
0

嗨,我只是想顯示圖像的推送通知。即時通訊使用下面的代碼,即時消息不知道我在哪裏做錯了它花了我超過3周,我經歷了很多鏈接,但仍然無法修復。下面是我的應用程序委託代碼推送圖像的通知 - iOS - Swift

AppDelegate.Swift

import UIKit 
import UserNotifications 

var deviceTokenString:String = "" 
var badgeCount = 0 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { 

var window: UIWindow? 


func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 

    // Push Notification 

    if #available(iOS 10.0, *) 
    { 
     let center = UNUserNotificationCenter.current() 
     center.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in 

      // actions based on whether notifications were authorised or not 

      guard error == nil else { 

       //Display Error.. Handle Error.. etc.. 

       return 
      } 

      if granted 
      { 

       //Do stuff here.. 

      } 

      else { 

       //Handle user denying permissions.. 

      } 

     } 

     application.registerForRemoteNotifications() 
    } else { 
     // Fallback on earlier versions 
    } 




    registerForRemoteNotification() 


    // iOS 10 support 
    if #available(iOS 10, *) { 
     UNUserNotificationCenter.current().requestAuthorization(options:[.alert, .sound]){ (granted, error) in } 
     application.registerForRemoteNotifications() 
    } 
     // iOS 9 support 
    else if #available(iOS 9, *) { 
     UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil)) 
     UIApplication.shared.registerForRemoteNotifications() 
    } 
     // iOS 8 support 
    else if #available(iOS 8, *) { 
     UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil)) 
     UIApplication.shared.registerForRemoteNotifications() 
    } 
     // iOS 7 support 
    else { 
     application.registerForRemoteNotifications(matching: [.sound, .alert]) 
    } 

    return true 
} 

func registerForRemoteNotification() { 
    if #available(iOS 10.0, *) { 
     let center = UNUserNotificationCenter.current() 
     center.delegate = self 
     center.requestAuthorization(options: [.sound, .alert]) { (granted, error) in 
      if error == nil{ 
       UIApplication.shared.registerForRemoteNotifications() 

      // UIApplication.shared.applicationIconBadgeNumber = 5 
      } 
     } 
    } 
    else { 
     UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert], categories: nil)) 
     UIApplication.shared.registerForRemoteNotifications() 

     // UIApplication.shared.applicationIconBadgeNumber = 5 
    } 
} 

func incrementBadgeNumberBy(badgeNumberIncrement: Int) 
{ 
    let currentBadgeNumber = UIApplication.shared.applicationIconBadgeNumber 
    let updatedBadgeNumber = currentBadgeNumber + badgeNumberIncrement 
    if (updatedBadgeNumber > 0) 
    { 
     UIApplication.shared.applicationIconBadgeNumber = updatedBadgeNumber 
    } 
    else 
    { 
     UIApplication.shared.applicationIconBadgeNumber = 0 
    } 
} 

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { 
    print("Couldn't register: \(error)") 
} 

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { 

    deviceTokenString = deviceToken.hexString() 

    // deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)}) 
    print("device token: \(deviceTokenString)") 


} 

// Push notification received 
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any]) { 
    // Print notification payload data 

    badgeCount = badgeCount + 1 
    self.incrementBadgeNumberBy(badgeNumberIncrement: badgeCount) 

    print("Push notification received: \(data)") 

} 

// Notification will present call back 
@available(iOS 10.0, *) 
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { 
    completionHandler([.alert, .sound, .badge]) 


    print("UserInfo: \(notification.request.content.userInfo)") 

    var userinfo = NSDictionary() 
    userinfo = notification.request.content.userInfo as NSDictionary 

    let imgData = userinfo.value(forKey: "data")! as! NSDictionary 

    let url = imgData.value(forKey: "attachment-url") 

    let imgUrl = URL(string: url as! String)! 

    // 1. Create Notification Content 
    let content = UNMutableNotificationContent() 


    // 2. Create Notification Attachment 

    URLSession.shared.downloadTask(with: imgUrl) 
    {(location, response, error) in 

     print("location: \(location!)") 

     if error == nil 
     { 
      if let location = location 
      { 
       // Move temporary file to remove .tmp extension 

       let tmpDirectory = NSTemporaryDirectory() 

       let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent) 

       print("tmpFile: \(tmpFile)") 

       let tmpUrl = URL(string: tmpFile)! 

       print("tmpUrl: \(tmpUrl)") 

       try! FileManager.default.moveItem(at: location, to: tmpUrl) 

       // Add the attachment to the notification content 

       if let attachment = try? UNNotificationAttachment(identifier: "attachment", url: tmpUrl) { 

        content.attachments = [attachment] 

        print("attachment: \(content.attachments)") 

        // 3. Create Notification Request 

        let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue, 

                  content: content, trigger: nil) 

        content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)" 
        content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)" 
        content.sound = UNNotificationSound.default() 
        content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber; 
        content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue 

        // 4. Add to NotificationCenter 

        let center = UNUserNotificationCenter.current() 

        center.add(request) 
       } 
      } 
     } 
     else 
     { 
      print("Error: \(error!)") 
     } 
     }.resume() 
} 

@available(iOS 10.0, *) 
// Notification interaction response call back 
func userNotificationCenter(_ center: UNUserNotificationCenter, 
          didReceive response: UNNotificationResponse, 
          withCompletionHandler completionHandler: @escaping() -> Void) { 

    print("\(response.notification.request.content.userInfo)") 

    var userinfo = NSDictionary() 
    userinfo = response.notification.request.content.userInfo as NSDictionary 

    let imgData = userinfo.value(forKey: "data")! as! NSDictionary 

    let url = imgData.value(forKey: "attachment-url") 

    let imgUrl = URL(string: url as! String)! 

    // 1. Create Notification Content 
    let content = UNMutableNotificationContent() 
    content.title = "\(userinfo.value(forKeyPath: "aps.alert.title")!)" 
    content.body = "\(userinfo.value(forKeyPath: "aps.alert.body")!)" 
    content.sound = UNNotificationSound.default() 
    content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber; 
    content.categoryIdentifier = String.UNNotificationCategory.Normal.rawValue // 設置通知類型標示 

    // 2. Create Notification Attachment 

    URLSession.shared.downloadTask(with: imgUrl) { (location, response, error) in 

     if let location = location { 

      // Move temporary file to remove .tmp extension 

      let tmpDirectory = NSTemporaryDirectory() 

      let tmpFile = "file://".appending(tmpDirectory).appending(imgUrl.lastPathComponent) 

      let tmpUrl = URL(string: tmpFile)! 

      try! FileManager.default.moveItem(at: location, to: tmpUrl) 



      // Add the attachment to the notification content 

      if let attachment = try? UNNotificationAttachment(identifier: "", url: tmpUrl) { 

       content.attachments = [attachment] 
      } 
     } 

     // Serve the notification content 

     // self.contentHandler!(content) 

     }.resume() 

    //  if let attachement = try? UNNotificationAttachment(identifier: "attachment", url: imgUrl, options: nil) 
    //  { 
    //   content.attachments = [attachement] 
    //  } 

    // 3. Create Notification Request 
    let request = UNNotificationRequest.init(identifier: String.UNNotificationRequest.NormalLocalPush.rawValue, 
              content: content, trigger: nil) 

    // 4. Add to NotificationCenter 
    let center = UNUserNotificationCenter.current() 
    center.add(request) 

    let responseNotificationRequestIdentifier = response.notification.request.identifier 

    if responseNotificationRequestIdentifier == String.UNNotificationRequest.NormalLocalPush.rawValue || 
     responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithTrigger.rawValue || 
     responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI1.rawValue || 
     responseNotificationRequestIdentifier == String.UNNotificationRequest.LocalPushWithCustomUI2.rawValue { 

     let actionIdentifier = response.actionIdentifier 
     switch actionIdentifier { 
     case String.UNNotificationAction.Accept.rawValue: 

      break 
     case String.UNNotificationAction.Reject.rawValue: 

      break 
     case String.UNNotificationAction.Input.rawValue: 

      break 
     case UNNotificationDismissActionIdentifier: 

      break 
     case UNNotificationDefaultActionIdentifier: 

      break 
     default: 
      break 
     } 
    } 
    completionHandler(); 
} 


} 

extension Data 
{ 
func hexString() -> String 
{ 
    return self.reduce("") { string, byte in 
     string + String(format: "%02X", byte) 
    } 
} 
} 

而下面是我的擴展代碼使用自定義推送通知其IM,

Extension.swift

import Foundation 

extension String { 

enum UNNotificationAction : String { 
    case Accept 
    case Reject 
    case Input 
} 

enum UNNotificationCategory : String { 
    case Normal 
    case Cheer 
    case CheerText 
} 

enum UNNotificationRequest : String { 
    case NormalLocalPush 
    case LocalPushWithTrigger 
    case LocalPushWithCustomUI1 
    case LocalPushWithCustomUI2 
} 
} 

extension URL { 

enum ResourceType : String { 
    case Local 
    case Local1 
    case Remote 
    case AttachmentRemote 
} 

static func resource(type :ResourceType) -> URL 
{ 
    switch type { 
    case .Local: 
     return Bundle.main.url(forResource: "cheer", withExtension: "png")! 
    case .Local1: 
     return Bundle.main.url(forResource: "hahaha", withExtension: "gif")! 
    case .Remote: 
     return URL(string: "http://ww1.sinaimg.cn/large/65312d9agw1f59leskkcij20cs0csmym.jpg")! 
    case .AttachmentRemote: 
     return URL(string: "https://assets-cdn.github.com/images/modules/open_graph/github-mark.png")! 
    } 
    } 
} 

extension URLSession { 

class func downloadImage(atURL url: URL, withCompletionHandler completionHandler: @escaping (Data?, NSError?) -> Void) { 
    let dataTask = URLSession.shared.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in 
     completionHandler(data, error as NSError?) 
    } 
    dataTask.resume() 
} 
} 

和我的Api響應是,

[AnyHashable("aps"): 
{ 
alert =  { 
    body = test; 
    title = "N-Gal"; 
}; 
"mutable-content" = 1; 
sound = default; 
}, 
AnyHashable("data"): 
{ 
"attachment-url" = "https://www.n-gal.com/image/cache/catalog/HomeBanner/Banners/1172X450-N-Gal-Footwear-Banner-100x100.jpg"; 
}] 

此代碼基於教程https://github.com/maquannene/UserNotifications。請給我一個解決方案來解決這個問題...在此先感謝...!

+0

你能說出它失敗的地方嗎?它是否收到來自APNS的推送通知?你可以創建一個本地通知_without_圖像?圖像是否被下載? – GregHNZ

+0

我沒有得到任何錯誤,並且即時接收推送通知,但沒有圖像,並且圖像正在下載並且文件路徑類似於file:/// private/var/mobile/Containers/Data/Application/552F6491-A95C-463E-8924-FD8BD53A629D/tmp/NG0330-(1)-100x100.jpg –

回答

5

從您的代碼片段中,我得出結論,您正在談論遠程通知。這是一個重要的區別。如果你想「豐富」遠程通知(例如添加圖像),你需要一個UNNotificationServiceExtension

對於本地通知,應用程序創建 休息通知的內容的時候增加了附件。 要將附件添加到遠程 通知,請在通知服務發佈前使用通知服務擴展來修改 。有關實現通知服務擴展的更多信息 ,請參閱 UNNotificationServiceExtension

來源:Apple documentation。 (重點是我的)

該擴展程序存在於您的應用程序之外,並且在用戶看到遠程通知之前被稱爲之前。這樣您就有機會在通知計劃交付之前加載所有遠程資源。有關擴展程序生命週期及其與主機應用程序通信方式的詳細信息,請參閱App Extension Programming Guide

要添加在Xcode的延長,去File > New > Target並選擇通知服務擴展

New target pane

這將創建一個新的擴展目標並將其嵌入主機目標:

New extension target

NotificationService.swift文件中,您可以找到可登錄的入口點自定義通知內容。

class NotificationService: UNNotificationServiceExtension { 

    var contentHandler: ((UNNotificationContent) -> Void)? 
    var bestAttemptContent: UNMutableNotificationContent? 

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { 
     self.contentHandler = contentHandler 
     bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) 

     if let bestAttemptContent = bestAttemptContent { 
      // Modify the notification content here... 
      bestAttemptContent.title = "\(bestAttemptContent.title) [modified]" 

      contentHandler(bestAttemptContent) 
     } 
    } 

    override func serviceExtensionTimeWillExpire() { 
     // Called just before the extension will be terminated by the system. 
     // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. 
     if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { 
      contentHandler(bestAttemptContent) 
     } 
    } 

} 

請務必查看UNNotificationServiceExtension class overview瞭解更多詳情。

+0

謝謝.....我已經創建了一個服務擴展,但是我犯了一個小錯誤。無論如何感謝您的答案.. Upvoted!爲了一個簡潔的答案... –