# Rich Notifications

To implement rich notifications you will have to create a new Notification Service Target that will be responsible for downloading the media of the notification and attach it to the notification object.

In Xcode go to File -> New -> Target and choose Notification Service Extension

{% hint style="info" %}
Keep in mind that notifications don't have much time to download the media attached, if the download doesn't finish in a short period of time the notification will be delivered without the media.
{% endhint %}

To handle MPush attachments add this your `NotificationService` should look like this:

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

    if let bestAttemptContent = bestAttemptContent {
        if let mediaUrl = request.content.userInfo["media_url"] as? String, let fileUrl = URL(string: mediaUrl) {
            downloadMedia(fileUrl: fileUrl, request: request, bestAttemptContent: bestAttemptContent) {
                contentHandler(bestAttemptContent)
            }
        } else {
            contentHandler(bestAttemptContent)
        }
    }
}

func downloadMedia(fileUrl: URL, request: UNNotificationRequest, bestAttemptContent: UNMutableNotificationContent, completion: @escaping () -> Void) {
    let task = URLSession.shared.downloadTask(with: fileUrl) { (location, _, _) in
        if let location = location {
            let tmpDirectory = NSTemporaryDirectory()
            let tmpFile = "file://".appending(tmpDirectory).appending(fileUrl.lastPathComponent)
            let tmpUrl = URL(string: tmpFile)!
            do {
                try FileManager.default.moveItem(at: location, to: tmpUrl)

                var options: [String: String]? = nil
                if let type = request.content.userInfo["media_type"] as? String {
                    options = [String: String]()
                    options?[UNNotificationAttachmentOptionsTypeHintKey] = type
                }
                if let attachment = try? UNNotificationAttachment(identifier: "media." + fileUrl.pathExtension, url: tmpUrl, options: options) {
                    bestAttemptContent.attachments = [attachment]
                }
                completion()
            } catch {
                completion()
            }
        }
    }
    task.resume()
}

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)
    }
}
```

With this code, we download the attachment, if exists, and move it to a temporary directory. Then we add it to our notification with

```bash
if let attachment = try? UNNotificationAttachment(identifier: "media." + fileUrl.pathExtension, url: tmpUrl, options: options) {
    bestAttemptContent.attachments = [attachment]
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mpush.cloud/ios-sdk/rich-notifications.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
