【问题标题】:How to show beacon notification only once a day in Swift?如何在 Swift 中每天只显示一次信标通知?
【发布时间】:2018-09-15 20:53:53
【问题描述】:

当检测到信标信号时,我的信标通知会随时触发。如何将其限制为每天仅接收一次通知?

我实施了日期检查,但这没有帮助。 if/else 检查工作正常,但忽略此检查会触发信标通知

非常感谢任何解决方法的建议!

这里是我的代码 sn-p:

class ViewController: UIViewController, CLLocationManagerDelegate {

    let locationManager = CLLocationManager()

    let date = Date()
    let calendar = Calendar.current

    override func viewDidLoad() {
        super.viewDidLoad()

        locationManager.delegate = self
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = 10
        locationManager.distanceFilter = 100
        locationManager.startUpdatingLocation()


        let year = calendar.component(.year, from: date)
        let month = calendar.component(.month, from: date)
        let day = calendar.component(.day, from: date)
        let currentDate = "\(year)\(month)\(day)"
        var savedDate = UserDefaults.standard.string(forKey: "savedDate") ?? "12345"

        print(currentDate)
        print(savedDate)

        if (savedDate == currentDate){
            print("same date - no action")
        } else {
            savedDate = currentDate
            UserDefaults.standard.set(savedDate, forKey: "savedDate")
            print(savedDate + " execute program")

            let beaconRegion = CLBeaconRegion(proximityUUID: UUID(uuidString: "13D9F4C7-A68D-46F4-8D35-4BA7F64BC417")!, identifier: "estimote")
            beaconRegion.notifyOnEntry = true
            beaconRegion.notifyOnExit = false

            let content = UNMutableNotificationContent()
            content.title = "???? Daily beacon check! ????"
            content.subtitle = "Receive a new info every day!"
            content.body = "ONLY ONCE A DAY WE SUPPLY INFO!"
            content.sound = .default
            content.badge = 1

            let trigger = UNLocationNotificationTrigger(region: beaconRegion, repeats: true)
            let identifier = "estimote"
            let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)
            UNUserNotificationCenter.current().removeAllPendingNotificationRequests()

            UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
            UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
            })

            self.locationManager.startRangingBeacons(in: beaconRegion)

        }
    }

【问题讨论】:

  • 这看起来是一个非常简单的调试问题。你做了正确的事,在我看到print(currentDate)print(savedDate) 的地方添加了两个调试语句。这些打印出来的是什么?这个问题的答案应该可以让您知道为什么您的程序无法运行。

标签: swift beacon


【解决方案1】:

通过设置

let trigger = UNLocationNotificationTrigger(region: beaconRegion, repeats: true)
let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: trigger)

您基本上是在告诉程序在满足 beaconRegion 条件时关闭并自动发送通知。如果您总是想要通知并让系统为您处理它,那会很舒服。但是您无法在此时进行干预,因为它会自动运行。

您可以做的是手动处理通知,并检查是否应该在每次检测到信标时发送通知。为此使用locationManager(didRangeBeacons beacons:in region:) 委托函数:

let locationManager = CLLocationManager()
override func viewDidLoad() {
    super.viewDidLoad()

    // Setup beacon tracking once
    locationManager.delegate = self
    locationManager.requestAlwaysAuthorization()
    locationManager.desiredAccuracy = 10
    locationManager.distanceFilter = 100
    locationManager.startUpdatingLocation()
    let beaconRegion = CLBeaconRegion(proximityUUID: UUID(uuidString: "13D9F4C7-A68D-46F4-8D35-4BA7F64BC417")!, identifier: "estimote")
    beaconRegion.notifyOnEntry = true
    beaconRegion.notifyOnExit = false

    // Start looking for beacons
    self.locationManager.startRangingBeacons(in: beaconRegion)
}

// Handle beacons in range
func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion) {
    let now = Date()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyyMMdd"
    let nowString = formatter.string(from: now)

    // Check if notified ever (lastTime != nil) and if notified today
    if let lastTime = UserDefaults.standard.string(forKey: "savedDate"), lastTime == nowString {
        // Already notified today, skip
        print("same date - no action")
        return
    }

    // Your notification code
    let content = UNMutableNotificationContent()
    content.title = "? Daily beacon check! ?"
    content.subtitle = "Receive a new info every day!"
    content.body = "ONLY ONCE A DAY WE SUPPLY INFO!"
    content.sound = UNNotificationSound.default()
    content.badge = 1

    let identifier = "estimote"
    let request = UNNotificationRequest.init(identifier: identifier, content: content, trigger: nil)

    UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
        if error != nil {
          print("Error showing notification: \(error!.localizedDescription)")
        } else {
          print("Notification shown")
        }
    })

    UserDefaults.standard.set(nowString, forKey: "savedDate")
}

【讨论】:

  • 非常感谢您的全面解释!
  • 第一次运行 -> lastTime != nowString: print("Notification shown") 弹出但信标不发送任何消息,此后代码通过 if 语句运行多次并打印 ("same date - no行动”)。如何解决这个问题?非常感谢!
  • 如果完成处理程序运行,到那时一切都应该没问题。检查完成处理程序if error != nil { print("Error: \(error!.localizedDescription)") }error变量的内容@
  • 您好 Benno,非常感谢您的帮助和支持。第一次运行代码在日志中显示以下内容: 通知显示相同日期 - 无操作相同日期 - 无操作相同日期 - 无操作相同日期 - 无操作相同日期 - 无操作 第一次运行将 lastTate 设置为 nowString即使 lastTime 与 nowString 不同,也不会显示任何通知。此后,“同一日期 - 不采取任何行动”被打印了好几次。完成处理程序没有显示错误。你知道如何解决这个问题吗?非常感谢和最好的问候!
  • 您希望通知每天显示一次,对吗?通知在该日期第一次发送,并且日期(例如 20180930)保存为用户默认值。下次信标进入范围时,加载 lastTime(let lastTime = UserDefaults... 并与当天比较。如果仍然是同一天(lastTime == nowString),则跳过通知。第二天 lastTime 20180930 不等于nowString 20181001 运行下半部分代码,再次发送通知。这不是你想要的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多