Push Notifications Tutorial for iOS: Rich Push Notifications | raywenderlich.com

Learn how to modify and enhance push notifications before they are presented to the user, how to create custom UI around your push content, and more!

This is a companion discussion topic for the original entry at https://www.raywenderlich.com/8277640-push-notifications-tutorial-for-ios-rich-push-notifications

Excellent tutorial I really appreciated. However, I would have appreciated that the server side is in php. It would have been the only tutorial about an independent server.

Anyway, tanks a lot for that super work.

Hi Mark,
Awesome tutorial. Thank you

I have seen three different tutorials on RW for service extension.
one use dataTask another is uses downloadTask and another is just using Data(contentsOf: url).

I’m confused as to which I should be using. All three currently work for me, but considering weird bugs reported online that images sometimes don’t get downloaded I wonder which approach offers best solution.

Any idea?

Also what is the reason to use an App Group? I watched the WWDC videos and as long as you download and attach the image to the notification then it should work

@ski081 Can you please help with this when you get a chance? Thank you - much appreciated! :]

Hi @xhome_ios. All 3 approaches are valid. Really, it’s just a matter of choosing which one fits the scenario you are coding for. I chose using a data task because it’s simple, easy to understand, and widely used. The reports online of the service extension failing could be for a variety of reasons. The extension only gets a short amount of processing time to do its work, so if anything takes too long (spotty network connection, asset excessively large), the task could fail and the image will not download properly.

I hope this helps!


I’m sorry, I’m not used to the RW’s messaging system. Just noticed your reply.

Got it. Thank you. I have 2 followup questions

Q1: If all I do in notification service extension is that I download the image, then does the provisioning profile of the service extension need any certain capabilities? Like Background task or push notifications?

I’ve added logs every where. So far without any capabilities added I have a 95% success rate, but I sometimes get -1001 (timeout error) status code for the network calls I make. Which I assume is kinda expected.

I also occasionally see 513 error from the file directory.

Q2: [“NSUnderlyingError”: Error Domain=NSPOSIXErrorDomain Code=1 “Operation not permitted”, “NSFilePath”: /private/var/mobile/Containers/Data/PluginKitPlugin/FE37CB44-E7C3-497D-95B2-45091619EF80/tmp/FE4D866A-2627-4499-9A5D-2832C39C7296-204-0000000751635A88/image]

Do you have any idea about the 513 error?

Hi @xhome_ios.

  1. No, you should not need any additional permissions outside of what I outlined in the tutorial.
  2. I’ve not seen that error before, and it seems like an underlying iOS error. There are a lot of factors that could come into play here, including network latency, and that, coupled with the time the operating system is giving you to complete your work could be creating this issue. I’m sorry I don’t have any additional troubleshooting steps, especially if this is an intermittent error.

@ski081 I figured it out :smiley:

  • turn off your phone
  • turn it on
  • don’t enter password ie don’t unlock it. At this point the device is a completeUntilFirstUserAuthentication and you can’t create a directory…
  • receive push notification

It’s basically a security design architecture in place by Apple.

You either have to change it to:

try data.write(to: tmpFileURL, options: [.noFileProtection])

and then we’d be able to access files during boot time or in locked state.

Or just allow it to fail until user enters their password for the first time.

@xhome_ios - wow, never thought about the default protection state of the device before it’s been unlocked. Great catch, and thanks for replying back!

1 Like

I am stuck at the part trying to get the notification title to change. I can get notifications to come through on my phone, but no changes to the initial notification occur. I put a print statement inside the didRecieve of the NotificationService.swift and it looks like it never gets called when I receive a notification. I’m running iOS 14.3, any ideas on what could be wrong?

Hi @filipee26. Sounds like something wrong with your configuration or with the push payload itself. I’ve seen this happen when the mutable-content entry is not set or is in the wrong place. Maybe check that?

Hi guys, thanks for this excellent tutorial! I appreciate that!

However, I am not able to get the notification service extension and the notification content extension to work. As @filipee26 says it seems that the extensions never gets called…
(No breakpoint hit after attaching / running the extension)

I downloaded the source code for the final project and updated the app values according to the Getting Started instructions but I only get the ‘normal’ notification without image and custom UI.

I suspect that there are breaking changes on Apple’s side that prevent the current approach. Can this be? I did some other tutorials but got the same result. I would be very happy to get some help.

Thanks again for your great work!

XCode 12.4
iOS 14.4.2

Hi @ski081,
Thanks for the tutorial, I had a quick question. Can you elaborate on why the Content Extension needs to be a part of the app group and the Service Extension does not have this step? What role does the app group play here and can this be achieved without it?

Hi @thorkane.

The Service Extension doesn’t offer any functionality except showing some metadata about the push and downloading the icon for display on the banner. It’s able to do this directly without reading any additional data from the app.

The Content Extension relies on reading some data from the core data store, which is shared with the iOS app. A common way to do this is to place the core data store in the app container so it is accessible by the extension and the app. In this way, both the extension and the app can read from the same data store.

Thanks for the quick response. So if you don’t need to share data with the app you do not need an app group. It is never inherently required. It all makes sense now, thanks for clearing it up.