I have notification that works well with only one time item. I need show my notification: 10:00 PM and 10:30 PM. How i can do that? Please tell me
My code:
NotificationManager.swift:
import UIKit
import UserNotifications
class NotificationManager
{
static let shared = NotificationManager()
let center = UNUserNotificationCenter.current()
func registerNotifications()
{
center.requestAuthorization(options: [.sound,.alert], completionHandler: {( granted, error) in })
}
func addNotificationWithCalendarTrigger(hour: Int, minute: Int)
{
let content = UNMutableNotificationContent()
content.title = "Hi"
content.body = "It,s new notification!"
content.sound = UNNotificationSound.default()
var components = DateComponents()
components.hour = hour
components.minute = minute
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: "calendar", content: content, trigger: trigger)
center.add(request) { (error) in
//handle error
}
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
timeForNotifications()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func timeForNotifications()
{
NotificationManager.shared.addNotificationWithCalendarTrigger(hour: 22, minute: 00)
}
}
might be a bit late but I think this is what you're looking for. You can set the notification to show up at 10:00 with the following code:
var components = DateComponents()
components.hour = 22
components.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: true)
let request = UNNotificationRequest(identifier: "calendar", content: content, trigger: trigger)
What I always do is replace components with date, but I think your option works as well.
var date = DateComponents()
date.hour = 22
date.minute = 00
let trigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
Hope this helped you out!
Related
I want to develop view that's loading data from Health kit (mindfulness time) so I used Timer every 1 minute to get a new data from Health kit, created by Apple watch but onReceive(Timer) are not refreshing a new data (it pass previous data only)
if I Open another app and come back to this app then it's show me a new data
import SwiftUI
struct LoadingView: View {
var healthStore : HealthStore? = HealthStore()
#State private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
#State var num : Int = 0
#Binding var showModal: Bool
var decription : String
// MARK: - BODY
var body: some View {
VStack (alignment: .center){
Spacer()
WatchView()
Spacer()
Text(decription)
.font(.callout)
.fontWeight(.semibold)
.padding(.horizontal,30)
Spacer()
}
.navigationBarBackButtonHidden(true)
.onReceive(timer) { _ in
if let healthStore = healthStore {
healthStore.requestAuthorization { success in
if success {
healthStore.getDailyMindfulnessTime { time in
print("\(time)")
}
} //: SUCCESS
}
}
}// ON RECEIVE
.onDisappear(perform: {
self.timer.upstream.connect().cancel()
})//ON DISAPPEAR
}
}
Health Store
import Foundation
import HealthKit
class HealthStore {
var healthStore : HKHealthStore?
var query : HKStatisticsCollectionQuery?
var querySampleQuery : HKSampleQuery?
init(){
// to check data is avaliable or not?
if HKHealthStore.isHealthDataAvailable(){
//Create instance of HKHealthStore
healthStore = HKHealthStore()
}
}
// Authorization
func requestAuthorization(compleion: #escaping(Bool)-> Void){
let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
let mindfulSampleType = HKSampleType.categoryType(forIdentifier: .mindfulSession)!
guard let healthStore = self.healthStore else { return compleion(false)}
healthStore.requestAuthorization(toShare: [], read: [stepType,mindfulSampleType]) { (success, error) in
compleion(success)
}
}
//Calculate steps count
func calculateSteps(completion : #escaping(HKStatisticsCollection?)->Void){
let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
let startDate = Calendar.current.date(byAdding: .day,value: -7, to: Date())
let anchorDate = Date.mondayAt12AM()
let daily = DateComponents(day:1)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date()
, options: .strictStartDate)
//cumulativeSum (Watch+Iphone)
query = HKStatisticsCollectionQuery(quantityType: stepType, quantitySamplePredicate: predicate, options: .cumulativeSum, anchorDate: anchorDate, intervalComponents: daily)
query!.initialResultsHandler = { query, statisticsCollection , error in
completion(statisticsCollection)
}
if let healthStore = self.healthStore, let query = self.query {
healthStore.execute(query)
}
}
// DailyMindfulnessTime
func getDailyMindfulnessTime(completion: #escaping (TimeInterval) -> Void) {
let sampleType = HKSampleType.categoryType(forIdentifier: .mindfulSession)!
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
let startDate = Calendar.current.startOfDay(for: Date())
let endDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictStartDate)
querySampleQuery = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: [sortDescriptor]) { (_, results, error) in
if error != nil {
print(" HealthKit returned error while trying to query today's mindful sessions. The error was: \(String(describing: error?.localizedDescription))")
}
if let results = results {
var totalTime = TimeInterval()
for result in results {
totalTime += result.endDate.timeIntervalSince(result.startDate)
}
completion(totalTime)
} else {
completion(0)
}
}
if let healthStore = self.healthStore, let querySampleQuery = self.querySampleQuery {
healthStore.execute(querySampleQuery)
}
}
}
extension Date {
static func mondayAt12AM() -> Date{
return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear,.weekOfYear],from: Date()))!
}
}
first of all you write in your question that you want to update every minute, but currently you update every second. TimeInterval is a typealias for Double and you pass it in your Timer as seconds. So in your case it should be:
#State private var timer = Timer.publish(every: 60, on: .main, in: .common).autoconnect()
Be aware this means onReceive is called after 60 seconds and not immediately.
And I tested your code and it worked fine for me. Unfortunately you didnt include your watch view so I dont know what you are doing in there.
I assumed num is the variable you wanted to update, so you need to call:
num += Int(time)
in your closure for getDailyMindfulnessTime.
If you want to display the time in your WatchView make sure to pass num as a Binding in there.
I know to how to create local notification in Swift 3( I am new in this part), However, I want to create something like below image. All tutorials in the web are too old and I do not what should I do.
As you can see before extending notification , there are 2 buttons. after extending also there are 2 buttons with red and blue color.
Updated
Thanks Joern
The slide gesture only show clear. Is there any settings for showing both clear and view
The red and blue buttons are only available in iOS versions prior to iOS 10. With iOS 10 the notifications design changed. The slide gesture is used for the standard actions Clear and View. The custom actions Snooze and Confirm will be displayed when you force touch the notification or pull it down (for devices without force touch). If you are using a device with force touch the View button might not be shown.
The buttons look different now:
So, here is how you implement Local Notifications with Swift 3 / 4:
For iOS versions prior to iOS 10:
If you are supporting iOS versions prior to iOS10 you have to use the old (deprecated with iOS 10) UILocalNotification:
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
registerLocalNotification()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
scheduleLocalNotification()
}
func scheduleLocalNotification() {
let localNotification = UILocalNotification()
localNotification.alertTitle = "Buy milk"
localNotification.alertBody = "Remember to buy milk from store"
localNotification.fireDate = Date(timeIntervalSinceNow: 3)
localNotification.soundName = UILocalNotificationDefaultSoundName
localNotification.category = "reminderCategory" // Category to use the specified actions
UIApplication.shared.scheduleLocalNotification(localNotification) // Scheduling the notification.
}
func registerLocalNotification() {
let reminderActionConfirm = UIMutableUserNotificationAction()
reminderActionConfirm.identifier = "Confirm"
reminderActionConfirm.title = "Confirm"
reminderActionConfirm.activationMode = .background
reminderActionConfirm.isDestructive = false
reminderActionConfirm.isAuthenticationRequired = false
let reminderActionSnooze = UIMutableUserNotificationAction()
reminderActionSnooze.identifier = "Snooze"
reminderActionSnooze.title = "Snooze"
reminderActionSnooze.activationMode = .background
reminderActionSnooze.isDestructive = true
reminderActionSnooze.isAuthenticationRequired = false
// Create a category with the above actions
let shoppingListReminderCategory = UIMutableUserNotificationCategory()
shoppingListReminderCategory.identifier = "reminderCategory"
shoppingListReminderCategory.setActions([reminderActionConfirm, reminderActionSnooze], for: .default)
shoppingListReminderCategory.setActions([reminderActionConfirm, reminderActionSnooze], for: .minimal)
// Register for notification: This will prompt for the user's consent to receive notifications from this app.
let notificationSettings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: [shoppingListReminderCategory])
UIApplication.shared.registerUserNotificationSettings(notificationSettings)
}
}
This will register the local notification and fires it 3 seconds after the user closes the app (for testing purposes)
For iOS 10 and later:
If you target your app to iOS 10 you can use the new UserNotifications framework:
import UIKit
import UserNotifications
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
registerUserNotifications()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
scheduleLocalNotification()
}
func registerUserNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
guard granted else { return }
self.setNotificationCategories()
}
}
func setNotificationCategories() {
// Create the custom actions
let snoozeAction = UNNotificationAction(identifier: "SNOOZE_ACTION",
title: "Snooze",
options: .destructive)
let confirmAction = UNNotificationAction(identifier: "CONFIRM_ACTION",
title: "Confirm",
options: [])
let expiredCategory = UNNotificationCategory(identifier: "TIMER_EXPIRED",
actions: [snoozeAction, confirmAction],
intentIdentifiers: [],
options: UNNotificationCategoryOptions(rawValue: 0))
// Register the category.
let center = UNUserNotificationCenter.current()
center.setNotificationCategories([expiredCategory])
}
func scheduleLocalNotification() {
let content = UNMutableNotificationContent()
content.title = "Buy milk!"
content.body = "Remember to buy milk from store!"
content.categoryIdentifier = "TIMER_EXPIRED"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 3, repeats: false)
// Create the request object.
let request = UNNotificationRequest(identifier: "Milk reminder", content: content, trigger: trigger)
// Schedule the request.
let center = UNUserNotificationCenter.current()
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
}
}
}
}
You can check out a demo app that uses the UserNotifications framework here
I want to add local notification in my app. I am filling information in textfields and set date, time and reminder before particular date selected for the exam. Anyone implement such a demo then please suggest me what to do.
Answer is based on what ever i understood, Please change the time and reminder string as per your requirement.
func scheduleNotification(InputUser:String) {
let now: NSDateComponents = NSCalendar.currentCalendar().components([.Hour, .Minute], fromDate: NSDate())
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let date = cal.dateBySettingHour(now.hour, minute: now.minute + 1, second: 0, ofDate: NSDate(), options: NSCalendarOptions())
let reminder = UILocalNotification()
reminder.fireDate = date
reminder.alertBody = InputUser
reminder.alertAction = "Cool"
reminder.soundName = "sound.aif"
reminder.repeatInterval = NSCalendarUnit.Minute
UIApplication.sharedApplication().scheduleLocalNotification(reminder)
print("Firing at \(now.hour):\(now.minute+1)")
}
Set up Daily basic Local Notification 1 Day before or you can be modified it with the help of specific date in Swift 3.1
import UIKit
import UserNotifications
fileprivate struct AlarmKey{
static let startWorkIdentifier = "com.Reminder.Notification" //Add your own Identifier for Local Notification
static let startWork = "Ready for work? Toggle To \"Available\"."
}
class AlarmManager: NSObject{
static let sharedInstance = AlarmManager()
override init() {
super.init()
}
//MARK: - Clear All Previous Notifications
func clearAllNotifications(){
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
} else {
UIApplication.shared.cancelAllLocalNotifications()
}
}
func addReminder(with _ hour: Int, minutes: Int){
clearAllNotifications()
var dateComponent = DateComponents()
dateComponent.hour = hour // example - 7 Change you time here Progrmatically
dateComponent.minute = minutes // example - 00 Change you time here Progrmatically
if #available(iOS 10.0, *) {
dateComponent.timeZone = TimeZone.autoupdatingCurrent
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponent, repeats: false) //Set here **Repeat** condition
let content = UNMutableNotificationContent()
content.body = AlarmKey.startWork //Message Body
content.sound = UNNotificationSound.default()
let notification = UNNotificationRequest(identifier: AlarmKey.startWorkIdentifier, content: content, trigger: trigger)
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().add(notification) {(error) in
if let error = error {
print("Uh oh! We had an error: \(error)")
}
}
} else {
//iOS *9.4 below if fails the Above Condition....
dateComponent.timeZone = NSTimeZone.system
let calender = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
let date = calender.date(from: dateComponent)!
let localNotification = UILocalNotification()
localNotification.fireDate = date
localNotification.alertBody = AlarmKey.startWork
localNotification.repeatInterval = NSCalendar.Unit.day
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.shared.scheduleLocalNotification(localNotification)
}
}
}
//This is optional method if you want to show your Notification foreground condition
extension AlarmManager: UNUserNotificationCenterDelegate{
#available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Swift.Void){
completionHandler([.alert,.sound])
}
}
I'm using swift 3. I want to add timeout to URLSession when doing download task. I did use configuration to change my setting, however, it doesn't work. The code didn't perform timeout... If the server didn't response quickly, it will fail.
Here is my code:
import Foundation
import UIKit
extension UIImageView {
func loadImage(url: URL) -> URLSessionDownloadTask {
let session: URLSession = {
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = 70
configuration.timeoutIntervalForResource = 70
return URLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
}()
let downloadTask = session.downloadTask(with: url, completionHandler: { [weak self] url, response, error in
if error == nil, let url = url, let data = try? Data(contentsOf: url), let image = UIImage(data: data) {
DispatchQueue.main.async {
if let strongSelf = self {
strongSelf.image = image
}
}
}
})
downloadTask.resume()
return downloadTask
}
}
Any comment is appreciated!!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
askForPermission()
}
#IBAction func addLocalNotification(_ sender: AnyObject) {
addLocalNotification()
}
func addLocalNotification() {
let content = UNMutableNotificationContent()
content.title = "iOS10.0"
content.body = "Hello Buddy"
content.sound = UNNotificationSound.default()
// Deliver the notification in five seconds.
let trigger = UNTimeIntervalNotificationTrigger.init(timeInterval: 5, repeats: false)
let request = UNNotificationRequest.init(identifier: "FiveSecond", content: content, trigger: trigger)
// Schedule the notification.
let center = UNUserNotificationCenter.current()
center.add(request) { (error) in
print(error)
}
print("should have been added")
}
func askForPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge]) { (granted, error) in
}
}
You have to implement a delegate to UNUserNotificationCenter to tell the system you want to display the notification while the app is running. See the sample here: https://github.com/jerbeers/DemoLocalNotification