Согласно рекомендациям Apple, вы можете получать push-уведомления как для фона, так и для состояния переднего плана, но когда дело доходит до состояния завершения, яблоко не позволяет автоматически открывать приложение или выполнять какие-либо действия. операции, если вы не запустите приложение через уведомление.
blockquote>Хотя вы можете обрабатывать уведомления во время завершения, используя параметры запуска во время запуска приложения.
Пример кодирования:
В вашей библиотеке импорта баз данных импорта AppDelegate.swift
import Firebase import FirebaseInstanceID import FirebaseMessaging import UserNotifications
Всякий раз, когда запуск приложения регистрируется для push добавьте следующие строки кода в didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { registerForPushNotifications(application: application) handleNotificationWhenAppIsKilled(launchOptions) return true } func handleNotificationWhenAppIsKilled(_ launchOptions: [UIApplicationLaunchOptionsKey: Any]?) { // Check if launched from the remote notification and application is close if let remoteNotification = launchOptions?[.remoteNotification] as? [AnyHashable : Any] { // Handle your app navigation accordingly and update the webservice as per information on the app. } }
Добавьте методы расширения appDelegate, чтобы зарегистрироваться для удаленного уведомления и получить токен устройства из APNS
//MARK: - Notifications related... extension AppDelegate { func registerForPushNotifications(application: UIApplication) { if #available(iOS 10.0, *) { // For iOS 10 display notification (sent via APNS) UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization( options: authOptions, completionHandler: {_, _ in }) // For iOS 10 data message (sent via FCM Messaging.messaging().delegate = self } else { let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) application.registerUserNotificationSettings(settings) } application.registerForRemoteNotifications() } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.map { String(format: "%02.2hhx", [112]) }.joined() let savedAPNSToken = UserDefaults.standard.object(forKey: "savedAPNSToken") as? String if savedAPNSToken != token { UserDefaults.standard.set(token, forKey: "savedAPNSToken") UserDefaults.standard.synchronize() Messaging.messaging().apnsToken = deviceToken } } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print(error.localizedDescription) } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { completionHandler(UIBackgroundFetchResult.newData) } }
Используйте следующие методы центра уведомлений для обработки уведомлений в основном и фоновом состояниях:
// MARK: - UNUserNotificationCenterDelegate @available(iOS 10, *) extension AppDelegate : UNUserNotificationCenterDelegate { // Receive displayed notifications for iOS 10 devices. func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { let userInfo = notification.request.content.userInfo completionHandler([.alert]) } /// Handle tap on the notification banner /// /// - Parameters: /// - center: Notification Center /// - response: Notification response func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo completionHandler() }
Обновление токена Firebase:
extension AppDelegate : MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) { // Note: This callback is fired at each app startup and whenever a new token is generated. let savedFCMToken = UserDefaults.standard.object(forKey: "savedFCMToken") as? String if savedFCMToken != fcmToken { UserDefaults.standard.set(fcmToken, forKey: "savedFCMToken") UserDefaults.standard.synchronize() // Update FCMToken to server by doing API call... } } }
Весь код шаблона должен быть помещен в заголовочный файл. Эта заливка решает соединение проблем (это - самый простой путь). Причина это происходит, состоит в том, потому что компиляторы компилируют каждый источник (.cc) файл отдельно из других файлов. С другой стороны, это должно знать то, что кодирует точно, это должно создать (т.е. что является T в шаблоне, заменен с), и это не имеет никакого другого способа знать это, если программист не говорит это явно или включает весь код, когда шаблонное инстанцирование происходит. Т.е. когда mylist.cc компилируется, он ничего не знает о mylist пользователях и какой код должен быть создан. С другой стороны, если listuser.cc компилируется, и весь код mylist присутствует, компилятор создает необходимый код mylist. Можно читать больше об этом в здесь или в Stroustrup.
Ваш код имеет проблемы, что, если пользователь запрашивает отрицательный или слишком большой (больше, чем сумма элементов в списке). И я не смотрел слишком много.
Кроме того, я не знаю, как u планируют использовать его, но Ваш оператор [] является O (N) время, которое, вероятно, легко приведет к O (N*N) циклы...
Учитывая Ваш исходный проблемный оператор,
Я должен использовать списки для своей программы и должен был решить, использую ли я станд.:: вектор или станд.:: список. Проблема с вектором состоит в том, что существует, не удаляют метод и со списком, что нет никакого оператора [].
нет никакой потребности создать Ваш собственный класс списка (это не мудрое проектное решение так или иначе, потому что std::list
не имеет виртуального деструктора, который является верным признаком, что он не предназначается, чтобы использоваться в качестве базового класса).
Можно все еще достигнуть того, что Вы хотите использовать std::vector
и std::remove
функция. Если v
a std::vector<T>
, затем удалить значение value
, можно просто записать:
#include <vector>
#include <algorithm>
T value = ...; // whatever
v.erase(std::remove(v.begin(), v.end(), value), v.end());
Векторы имеют метод стирания, который может удалить элементы. Разве это не достаточно?
В зависимости от Ваших потребностей необходимо использовать std::vector
(если Вам нужно, часто добавляет/удаляет в конце и произвольном доступе), или std::deque
(если Вам нужно, часто добавляет/удаляет в конце или вначале, и Ваш набор данных огромен, и все еще хотят произвольный доступ). Вот хорошее изображение, показывающее Вам, как принять решение:
(источник: adrinael.net)
В дополнение к другим превосходным комментариям лучший способ расширить стандартный контейнер не деривацией, но записью бесплатных функций. Например, посмотрите, как Строковые Алгоритмы Повышения могут использоваться для расширения std::string
и другие строковые классы.
Очевидный материал был уже детально описан:
Но методы Вы принимаете решение реализовать??
Нет никакой потребности назвать деструктор станд.:: список, потому что Вы уже происходите из станд.:: перечислите, когда деструктор призвал к myList автоматически станд.:: деструктор списка назовут.