【问题标题】:Launch a local notification at a specific time in iOS在 iOS 中的特定时间启动本地通知
【发布时间】:2017-09-10 09:13:19
【问题描述】:

我正在尝试创建一个计时器,该计时器会在用户设置的时间触发本地通知。我遇到的问题是我无法找到一种方法来设置本地通知在晚上 7:00 发出。研究此问题时发现的几乎所有方法都涉及本地通知在当前日期后的特定时间关闭。我试图让用户选择晚上 7:00,然后在那个时候关闭通知。从逻辑上讲,这可以通过拥有最终时间(用户选择的值)来实现 - 当前时间将为您提供时差。然而,我不完全确定如何做到这一点。

非常感谢有关该主题的任何帮助,谢谢。下面是我目前用来触发本地通知的代码。

let center = UNUserNotificationCenter.current()

content.title = storedMessage
content.body = "Drag down to reset or disable alarm"
content.categoryIdentifier = "alarm"
content.userInfo = ["customData": "fizzbuzz"]
content.sound = UNNotificationSound.init(named: "1.mp3")
content.badge = 1

let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeAmount, repeats: false)
let request = UNNotificationRequest(identifier: "requestAlarm", content: content, trigger: trigger)
    center.add(request)


center.delegate = self

【问题讨论】:

    标签: ios swift time timer uilocalnotification


    【解决方案1】:

    在 iOS 10 中,Apple 已弃用 UILocalNotification,这意味着是时候熟悉新的通知框架了。

    设置 这是一篇很长的文章,所以让我们从导入新的通知框架开始吧:

    // Swift
    import UserNotifications
    
    // Objective-C (with modules enabled)
    @import UserNotifications;
    

    您通过共享的 UNUserNotificationCenter 对象管理通知:

    // Swift
    let center = UNUserNotificationCenter.current()
    
    // Objective-C
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    

    授权 与旧的通知框架一样,您需要获得用户对您的应用程序将使用的通知类型的许可。在您的应用生命周期的早期提出请求,例如在 application:didFinishLaunchingWithOptions:. 您的应用第一次请求授权时,系统会向用户显示警报,之后他们可以从设置中管理权限:

    // Swift
    let options: UNAuthorizationOptions = [.alert, .sound];
    
    // Objective-C
    UNAuthorizationOptions options = UNAuthorizationOptionAlert + UNAuthorizationOptionSound;
    

    您使用共享通知中心提出实际授权请求:

    // Swift
    center.requestAuthorization(options: options) { (granted, error) in
        if !granted {
            print("Something went wrong")
        }
    }
    
    // Objective-C
    [center requestAuthorizationWithOptions:options
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (!granted) {
    NSLog(@"Something went wrong");
    }
    }];
    

    框架调用完成处理程序,并使用一个布尔值指示访问是否被授予,以及一个错误对象,如果没有发生错误,该对象将为 nil。

    注意:用户可以随时更改您应用的通知设置。您可以使用 getNotificationSettings 检查允许的设置。这将使用 UNNotificationSettings 对象异步调用完成块,您可以使用它来检查授权状态或单个通知设置:

     // Swift
     center.getNotificationSettings { (settings) in
         if settings.authorizationStatus != .authorized {
             // Notifications not allowed
         }
     }
    
     // Objective-C
     [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
     if (settings.authorizationStatus != UNAuthorizationStatusAuthorized) {
    // Notifications not allowed
     }
     }];
    

    创建通知请求 UNNotificationRequest 通知请求包含内容和触发条件:

    通知内容

    通知的内容是 UNMutableNotificationContent 的一个实例,并根据需要设置了以下属性:

    title:包含警报主要原因的字符串。

    subtitle:包含警报字幕的字符串(如果需要)

    body:包含警报消息文本的字符串

    徽章:应用图标上显示的数字。

    声音:发出警报时播放的声音。使用 UNNotificationSound.default() 或从文件创建自定义声音。 launchImageName:启动应用程序响应通知时使用的启动图像名称。

    userInfo:要传入通知的自定义信息字典 附件:一组 UNNotificationAttachment 对象。用于包含音频、图像或视频内容。

    请注意,在本地化像标题这样的警报字符串时,最好使用localizedUserNotificationString(forKey:arguments:),它会延迟加载本地化,直到通知发送。

    一个简单的例子:

     // Swift
     let content = UNMutableNotificationContent()
     content.title = "Don't forget"
     content.body = "Buy some milk"
     content.sound = UNNotificationSound.default()
    
     // Objective-C
     UNMutableNotificationContent *content = [UNMutableNotificationContent new];
     content.title = @"Don't forget";
     content.body = @"Buy some milk";
     content.sound = [UNNotificationSound defaultSound];
    

    通知触发器

    根据时间、日历或位置触发通知。触发器可以重复:

    时间间隔:在几秒钟后安排通知。比如五分钟触发:

     // Swift
     let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 300, repeats: false)
    
     // Objective-C
     UNTimeIntervalNotificationTrigger *trigger =     [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:300
                                  repeats:NO];
    

    日历:在特定日期和时间触发。触发器是使用日期组件对象创建的,这使得某些重复间隔更容易。要将 Date 转换为其日期组件,请使用当前日历。例如:

     // Swift
     let date = Date(timeIntervalSinceNow: 3600)
     let triggerDate = Calendar.current.dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
    
     // Objective-C
     NSDate *date = [NSDate dateWithTimeIntervalSinceNow:3600];
     NSDateComponents *triggerDate = [[NSCalendar currentCalendar]   
              components:NSCalendarUnitYear +
              NSCalendarUnitMonth + NSCalendarUnitDay +
              NSCalendarUnitHour + NSCalendarUnitMinute +
              NSCalendarUnitSecond fromDate:date];
    

    从日期组件创建触发器:

     // Swift
     let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
    
     // Objective-C
     UNCalendarNotificationTrigger *trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerDate
                                         repeats:NO];
    

    要创建以特定间隔重复的触发器,请使用正确的日期组件集。例如,要让通知每天在同一时间重复,我们只需要小时、分钟和秒:

     let triggerDaily = Calendar.current.dateComponents([hour, .minute, .second], from: date)
     let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
    

    要让它每周重复一次,同时我们还需要工作日:

     let triggerWeekly = Calendar.current.dateComponents([.weekday, .hour, .minute, .second], from: date)
     let trigger = UNCalendarNotificationTrigger(dateMatching: triggerWeekly, repeats: true)
    

    调度

    内容和触发器都准备好后,我们创建一个新的通知请求并将其添加到通知中心。每个通知请求都需要一个字符串标识符以供将来参考:

     // Swift
     let identifier = "UYLLocalNotification"
     let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
    
     center.add(request, withCompletionHandler: { (error) in
         if let error = error {
             // Something went wrong
         }
     })
    
     // Objective-C
     NSString *identifier = @"UYLLocalNotification";
     UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier
                                  content:content trigger:trigger]
    
     [center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
      if (error != nil) {
        NSLog(@"Something went wrong: %@",error);
      }
      }];
    
    【解决方案2】:

    要在特定时间启动通知,请使用以下代码。

    let content = UNMutableNotificationContent()
    content.title = "Title"
    content.body = "Body"
    content.sound = UNNotificationSound.default()
                    
    let gregorian = Calendar(identifier: .gregorian)
    let now = Date()
    var components = gregorian.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)
                    
    // Change the time to 7:00:00 in your locale
    components.hour = 7
    components.minute = 0
    components.second = 0
                    
    let date = gregorian.date(from: components)!
                    
    let triggerDaily = Calendar.current.dateComponents([.hour,.minute,.second,], from: date)
    let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)
                  
                    
    let request = UNNotificationRequest(identifier: CommonViewController.Identifier, content: content, trigger: trigger)
    print("INSIDE NOTIFICATION")
                    
    UNUserNotificationCenter.current().add(request, withCompletionHandler: {(error) in
        if let error = error {
            print("SOMETHING WENT WRONG")
        }
    })                                
    

    并在特定的时间间隔内不断启动,例如每 2 分钟后使用下面的行触发。

    let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 120, repeats: true)
    

    【讨论】:

      【解决方案3】:

      对于 Swift 你可以使用这个代码:

        let calendar = Calendar.current
          let components = DateComponents(year: 2018, month: 05, day: 06, hour: 20, minute: 22) // Set the date here when you want Notification
          let date = calendar.date(from: components)
          let comp2 = calendar.dateComponents([.year,.month,.day,.hour,.minute], from: date!)
          let trigger = UNCalendarNotificationTrigger(dateMatching: comp2, repeats: true)
      
          let content = UNMutableNotificationContent()
          content.title = "Notification Demo"
          content.subtitle = "Demo"
          content.body = "Notification on specific date!!"
      
          let request = UNNotificationRequest(
              identifier: "identifier",
              content: content,
              trigger: trigger
          )
      
          UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
              if error != nil {
                  //handle error
              } else {
                  //notification set up successfully
              }
          })
      

      希望得到帮助。

      【讨论】:

        【解决方案4】:

        这是在特定时间添加通知的最简单方法,它基于 Apple 的开发者文档:https://developer.apple.com/documentation/usernotifications

        这是我在模块化函数中的实现:

        public func simpleAddNotification(hour: Int, minute: Int, identifier: String, title: String, body: String) {
            // Initialize User Notification Center Object
            let center = UNUserNotificationCenter.current()
        
            // The content of the Notification
            let content = UNMutableNotificationContent()
            content.title = title
            content.body = body
            content.sound = .default
        
            // The selected time to notify the user
            var dateComponents = DateComponents()
            dateComponents.calendar = Calendar.current
            dateComponents.hour = hour
            dateComponents.minute = minute
        
            // The time/repeat trigger
            let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
        
            // Initializing the Notification Request object to add to the Notification Center
            let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
        
            // Adding the notification to the center
            center.add(request) { (error) in
                if (error) != nil {
                    print(error!.localizedDescription)
                }
            }
        }
        

        【讨论】:

          【解决方案5】:

          试试这个

              let dateformateer = NSDateFormatter()
              dateformateer.timeStyle = .ShortStyle
          
              let notification = UILocalNotification()
              var datecomponent = NSDateComponents()
          
              datecomponent = NSCalendar.currentCalendar().components([NSCalendarUnit.Day,NSCalendarUnit.Month,NSCalendarUnit.Hour,NSCalendarUnit.Year, NSCalendarUnit.Minute],fromDate: Datepicker.date)
          
          
              var fixdate = NSDate()
              fixdate = NSCalendar.currentCalendar().dateFromComponents(datecomponent)!
              notification.fireDate = fixdate
              notification.alertTitle = "Title"
              notification.alertBody = "Body"
             UIApplication.sharedApplication().scheduleLocalNotification(notification)` 
          

          【讨论】:

          • 感谢您的回复,但是,我收到大量错误,其中一些我无法修复,还有一些折旧的方法。您能否针对第五行代码提供一个稍微更新的版本?再次感谢您迄今为止的帮助。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-04-10
          • 2022-12-16
          • 2018-01-11
          • 1970-01-01
          • 2016-11-06
          • 1970-01-01
          相关资源
          最近更新 更多