티스토리 뷰

iOS10부터 이미지 푸시를 보낼 수 있다.

iOS10에서는 앱 실행 중에도 앱내에서 처리 없이 상단 푸시를 볼 수 있다. (단, RemoteNotification 등록시 UNUserNotificationCenter를 사용하였을 경우)


우선 AppDelegate에서 푸시를 등록 해보자.

let center = UNUserNotificationCenter.current()

center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in

    print("granted = \(granted)")

}

center.delegate = self

application.registerForRemoteNotifications()


UNUserNotificationCenterDelegate를 추가해 보자.

// MARK: - UNUserNotificationCenterDelegate

extension AppDelegate: UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        print("UNUserNotificationCenterDelegate willPresent notification = \(notification)")

        completionHandler([.alert, .sound, .badge])

    }

    

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {

        print("UNUserNotificationCenterDelegate didReceive response = \(response)")

        

        completionHandler()

    }

}



우선, 다음과 같이 로컬 이미지 푸시를 보내보자.


코드는 아래와 같다.

let content = UNMutableNotificationContent()

content.title = "로컬 타이틀"

content.body = "로컬 바디"

content.sound = UNNotificationSound.default()

content.categoryIdentifier = "image-message"


let imageURLString = "https://i.ytimg.com/vi/7qkbRYM7YP8/maxresdefault.jpg"

if let imagePath = DownloadManager.image(imageURLString) {

    let imageURL = URL(fileURLWithPath: imagePath)

    do {

        let attach = try UNNotificationAttachment(identifier: "imate-test", url: imageURL, options: nil)

        content.attachments = [attach]

    } catch {

        print(error)

    }

}


// Deliver the notification in five seconds.

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)

let request = UNNotificationRequest(identifier: "FiveSecond", content: content, trigger: trigger) // Schedule the notification.

let center = UNUserNotificationCenter.current()

center.add(request) { (error : Error?) in

    if let theError = error {

        print(theError)

    }

}


이미지를  받아오는 부분을 처리하는 DownloadManager.swift는 아래와 같다.

open class DownloadManager: NSObject {

    open class func image(_ URLString: String) -> String? {

        let componet = URLString.components(separatedBy: "/")

        if let fileName = componet.last {

            let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)

            if let documentsPath = paths.first {

                let filePath = documentsPath.appending("/" + fileName)

                if let imageURL = URL(string: URLString) {

                    do {

                        let data = try NSData(contentsOf: imageURL, options: NSData.ReadingOptions(rawValue: 0))

                        if data.write(toFile: filePath, atomically: true) {

                            return filePath

                        }

                    } catch {

                        print(error)

                    }

                }

            }

        }

        

        return nil

    }

}


다음은 APNS를 통해서 이미지 푸시를 받아 보겠다.

File -> New -> Target -> Notification Service Extension 을 선택하고 "NotificationServiceExtension"로 이름을 줬다.




스키마를 활성화하는 팝업에서 Activate를 눌러 준다.



Targets에 적용 된 걸 확인 할 수 있다.


이미지 푸시를 받게 되면 Notification Service Extension의 NotificationService.swift 파일에서 아래 함수를 타게 된다. 아래 함수에서 이미지를 다운 받는 처리를 하고 필요에 따라 title, subtitle, body, badge를 임으로 바꿀 수 있다.


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]"

        

        if let imageURLString = bestAttemptContent.userInfo["image-url"] as? String {

            if let imagePath = DownloadManager.image(imageURLString) {

                let imageURL = URL(fileURLWithPath: imagePath)

                do {

                    let attach = try UNNotificationAttachment(identifier: "image-test", url: imageURL, options: nil)

                    bestAttemptContent.attachments = [attach]

                } catch {

                    print(error)

                }

            }

        }

        

        contentHandler(bestAttemptContent)

    }

}


푸시를 받을 Payload는 아래와 같다.

Payload 

 {

  "aps" : {

    "alert" : {

      "title" : "타이틀",

      "subtitle" : "서브타이틀",

      "body" : "바디"

    },

    "mutable-content": 1

  },

  "image-url": "https://i.ytimg.com/vi/7qkbRYM7YP8/maxresdefault.jpg"

}

- mutable-content: 1 -> Notification Service Extension를 이용하겠다는 의미이다.

- image-url -> 임으로 만든 필드로 이미지 주소를 넣었다.


이미지 푸시를 보내기 위해서 Easy APNs Provider를 사용하였다.

https://itunes.apple.com/kr/app/easy-apns-provider-push-notification-service-testing-tool/id989622350?mt=12


다음과 같이 Token을 등록하고 Certificate File을 선택하고 Connect to를 한 다음 Payload를 Raw로 선택한다음 위에 적힌 Payload를 입력하고 Send APN을 하면 된다.

복사할 때 쌍따움표를 다르게 인식해서 푸시가 안 갈 수도 있으니 그럴땐 쌍따움표를 직접 입력해 주자.



결과 화면은 아래와 같다.




소스

ImagePushExample.zip