I have an iOS app integrated with Parse.com in which I want to schedule push notifications for certain dates/times. I am storing a push notification time on PFInstallation objects for users who have an upcoming event. I have a scheduled job running on Parse CloudCode that queries for push notification times that need to be sent within the next minute. Is this a good way to architect this? If so, how can I send this push? Parse.Push takes a query for it's where field, but queries only return up to 1000 results which doesn't scale at all for a free app. Thus, I'm trying to use Parse.query.each() which has an unlimited number of results. However, now I'm unsure how to send a push to each installation this way? Do I need to create another query within my each() statement? That seems redundant and inefficient.
(Note that the push notification is a silent notification with the content-available flag set so local notifications are not an option. Also the notifications can be cancelled by the user so scheduling the notification with the CloudCode push schedule API is not an option since those pushes can't be cancelled.)
You say, you store push notifications time on the respective PFInstallation object to circumvent the lack of support for canceling a push notification through Parse, great. We'll call that column ScheduledPushDate; That's the easy part; +1. The part you want to accomplish is actually scheduling a push notification using the given date. Great. Another easy part; +1. The hard part is doing it the way you want; -2. Parse.Push is not only limited by the where field. A lot of variables come into play when sending a push, for example, Parse doesn't even consider any objects that don't have a valid deviceToken so you can omit those objects immediately. The problem your running into is not the push itself, its not how to query for validation, its simply comes down to canceling it. Sure you can always change the date in ScheduledPushDate to be something in the year 2025 or simply negating it altogether, but that doesn't matter because you've already given the notification a scheduled date with the payload. Keeping it simple, and according to your target (you tagged iOS, so this is an answer specifically to client-side resources since you don't want to use local notifications or cloud code) you won't be able to cancel it, because within the guidelines given, you can only construct a push notification so many ways with Parse (client-side, cloud code, dashboard), and as of right now, only one of those options allows a successful means to cancel the process, and it's through the dashboard/console.
Lets say you do it the way you are thinking about:
Execute scheduled job to search for push times that need be fired within the coming minute. What is a "coming minute". Lets say a users time is 11:35.46 (11am35m46sec) and they want to cancel the scheduled notification and cancelled it at that moment, but your job fired at 11:35.00? Realistically, how often will that happen, not many, but it will happen and can happen. You should always code for every circumstance a user will encounter, not just the ones you want to prevent.
Additionally, you would be exhausting almost all of your API request limits if you do have a scaleable app as mentioned.
Lastly, to answer your question, no you don't have to do an innerQuery or additional query within the query.each function, as it's job is to iterate over each result of a query
Related
We want to use push notifications to inform our users about new app features or great content. These will only be sent occasionally, but should go to all users of our app.
We've already implemented push notifications and calculate the badge number based on server side. This works fine when sending push notifications as transactional information (e.g. somebody has followed you), but if we send them to thousands or millions of users, obtaining and sending the badge count as payload seems to be crazy.
This would actually result not only in one database lookup for every user, but also for thousands (or millions) of calls to APN.
From what I found in the docs, I don't see any way around this, also because you have to keep the badge count in sync with your own data. So, if so many calls to APN are actually necessary, what is the best practice to do these calls? All in one giant burst, or maybe send smaller chunks (like 1.000 at a time) and then pause for a minute?! I can't find any recommendation on Apple's pages on how to handle this and what they expect.
I have an app that allows users to create recurrent events. Each one of the events may or may not have reminder/alerts at a specific time of day. If they have so, the app sends a local notification at that time of day.
Events are stored in CoreData.
Event(name: "Go to London",
date: 2020-04-03 21:40:55.419925+0200,
reminders: [2020-04-03 20:00:00.419925+0200,
2020-04-03 10:00:00.419925+0200,
2020-04-03 12:00:00.419925+0200]
)
An event may occur on each day of the year or everyday for the next X years.
A user may create unlimited number of events per day. And hence, the total number of notifications to be sent can easily surpasses 64 (total number of local notification that you can schedule in iOS). So I can not schedule all the notifications while the app is in foreground.
I need a mechanism to periodically schedule notifications if there are less than 64 notifications pending. This should be done even if the app is in the background.
I would be happy if you provide a solution or guide me towards finding a solution for this scenario.
info
I tried to set up a Timer that periodically checks total number of pending notifications and their due dates. . But it did not work, because timers won’t fire once the app goes in background.
I am not sure if I understand your problem right. But my impression is the following:
Your users set up and update a database of events where each event has a certain date and time.
They do this simply be entering new events into the database.
It is easy then to fetch the first n (say, 10) events from the database.
It is required to fetch more than one, since the delivery of a local notification is not guaranteed, see the docs:
Every attempt is made to deliver local and remote notifications in a
timely manner, but delivery isn't guaranteed.
Register these n local notifications with the notification center, and cancel any notification for events that are no longer among the n next ones. The docs say:
Typically, you cancel a request when conditions change and you no
longer need to notify the user. For example, if the user completes a
reminder, you would cancel any active requests associated with that
reminder. To cancel an active notification request, call the
removePendingNotificationRequests(withIdentifiers:) or
removePendingNotificationRequests(withIdentifiers:) method of
UNUserNotificationCenter.
So, even if your app is in the background or suspended, the local notification will wake it up, handle the event, remove it from the database, and update the n next events. Even if a notification could not be delivered (which is not probably, but possible), you could handle the missed event, and schedule the next ones.
I hope this meets your requirements!
Have you tried the background fetch feature? Official document link here.
And in my opinion, it would be better to use remote notification, just setup a simple server to store the users' data.
I'm building a reminders app that sends local notifications that repeat based on a user's custom settings. For example, I may send a notification every other day at 8pm. Every time I send one of these notifications, I'd like to replace any previous notification that might be displayed in the user's notification center already.
The new UserNotifications framework in iOS gets me close to being able to do this. As far as I can tell, notifications can be replaced in two ways:
Use a UNCalendarNotificationTrigger with repeats: true. Repeated triggers replace past ones.
Create a new UNNotificationRequest with the same identifier. Whenever a request is sent with the same identifier, it replaces all other instances.
Neither of these solutions quite work for me:
I can't use use repeating notifications because UNCalendarNotificationTrigger uses DateComponents for a repeating schedule which just isn't granular enough. My example above of "every other day at 8pm" can't be described with just DateComponents.
Because I need to schedule several notifications all at once, I must specify unique identifiers, and as such, they don't replace each other when displayed.
I was hoping service extensions would save me here. If I could execute code when I receive a notification, I could programmatically remove old notifications when new ones are triggered. Unfortunately, it appears as if service extensions only work for remote notifications. Even if I could use remote notifications (which is a whole can of worms by itself), this solution kind of bends the rules on what is allowed for service extensions.
Does anyone have any ideas on how to solve this, or am I destined to spam my users' notification centers?
My calendar app is not connected to Event Kit which allows me to create custom repeating intervals like "every 3 days, 29 times" etc.
Now i would like to add Notifications to my Events ... but my custom repeating events are limiting me in every possible way.
I think I have checked every possible solution:
UILocalNotification
UILocalNotification is limited to 64 events and NSCalendarUnit's in-built Unit Time Intervals aren't very flexible.
1 event repeated every 2 days will fill this up very quickly
Should i reschedule 64 Notifications on every app start and beg the user to start the app regularly? Not running the app for a while will not reschedule notifications.
Event Kit (Calendars & Reminders)
I could create a calendar or Reminder list, generate single events from the custom repeating events and add notifications here. But the user can edit this, which will cause confusion.
I can't synch this back to my app.
Should i create a calendar or reminder list for Alerts and hope that the user will not touch this?
Apple Push Notification Service
Everywhere i can read: They are not reliable! There is no guarantee that push notifications will actually be delivered, even if the APNS server accepted them.
I think push notifications are not made for notifying the user at scheduled times as there is no guarantee they will arrive.
The question is what should i do, or what would you do in my case? No solution is perfect and i am hoping to find the most user friendly approach here. In case i am missing a approach, i would like to hear the alternative.
Edit:
Adding a another method for completeness.
UILocalNotification without repeats
don't offer the repeating of local notifications. The user can assign single Notifications to a event. After enabling the 65th notification, a popup will remind him that he has reached the system limit. This way you put the responsibility to the user. After reaching the limit he will be forced to focus on events that are not far in the future.
You could save all your events to core data and then every time the app is launched or when your main view appears load in all events for that week and set a scheduled local notification. Once the event is scheduled you set a flag in the entity eg hasBeenNotified.
Hope it helps.
I decided to offer local notifications without repeat functionality.
This decision was made after chatting with a few users.
Better to offer something than to offer nothing :)
Overview
I have an iOS app which sends local notifications at specific dates.
I just learned that I can only schedule 64 notifications at a given time.
There are cases when I can't schedule notifications as the 64 slots are filled.
So I store them in the database and when the user responds to a notification I check if there are any available slots and schedule the remaining notifications.
Problem
When the user doesn't respond to a notification my code is not executed so I am not able to schedule the remaining notifications.
Question
Is there a solution for this problem ?
can I execute a piece of code (house keeping) at certain times ?
is there any work around for this ?
You may not want to signal to the user there is a problem, but rather just do it in the background. If a user has 64 notifications for one app and hasn't opened the app, then they probably aren't using the app. Once a notification has fired it isn't in the array anymore. So you will have room every time a notification is fired off. They do however remain in notification centre, which you have to clear out yourself.
Its usually better to not present possible problems to the user, but rather handle them in a way that makes sense internally if that is an option. Look up the delegate methods for the appDelegate and you will most likely find ways you can handle what you are trying to do.
Thought I would make a post in case you wanted to accept the answer.
Best of luck.