在特定时间Swift每天调用一次函数

时间:2018-06-10 00:13:35

标签: ios swift uitableview timer delete-row

我有一个tableview,我想在每天的特定时间(用户输入选择器)清空它。以下是它主要使用的代码,但是让我们说用户在晚上7点打开应用程序,更新时间是晚上8点,数据不会被删除(这是正确的)但是当时间是在同一天晚上9点并且应用程序打开数据不会被删除(这是不正确的)。我认为这与lastRefreshDate正在更新应用程序的evreytime时间有关,必须等待lastRefreshDate而不是userPickedHour的24小时。该应用程序应该像这样工作有一个设定的时间晚上7点。因此,应用程序应该在第二天晚上7点或晚上7点之后删除数据,当用户打开应用程序时,如果用户在第二天晚上7点之前打开应用程序,则不应删除数据,

以下是代码:

class RefreshManager: NSObject {

static let shared = RefreshManager()
private let defaults = UserDefaults.standard
private let defaultsKey = "lastRefresh"
private let calender = Calendar.current



func loadDataIfNeeded(completion: (Bool) -> Void) {

    if isRefreshRequired() {
        // load the data
        defaults.set(Date(), forKey: defaultsKey)
        print("xxxxxx")
        completion(true)
    } else {
        print("yyyyyy")
        completion(false)
    }
}

private func isRefreshRequired(userPickedHour: Int = 16) -> Bool {
    let SleepPickerdate = UserDefaults.standard.object(forKey: "SleepDate") as? Date
    let userPickedHour = Calendar.current.component(.hour, from: (SleepPickerdate)!)
    print(userPickedHour)

    guard let lastRefreshDate = defaults.object(forKey: defaultsKey) as? Date else {
        return true
    }

    if let diff = calender.dateComponents([.hour], from: lastRefreshDate, to: Date()).hour,
        let currentHour =  calender.dateComponents([.hour], from: Date()).hour,
        diff >= 24, userPickedHour >= currentHour {

        print("Delete TableView")
        NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Delete"), object: nil)
        print(diff)
        return true

    } else {

        print("Don't Delete TableView")

        return false


      }
    }
  }



class ViewController: UIViewController {

let refreshManager = RefreshManager.shared

override func viewDidLoad() {
    super.viewDidLoad()

    refreshManager.loadDataIfNeeded() { success in
        print(success)
    }
  }
}

3 个答案:

答案 0 :(得分:5)

您无法保证您的应用每天都在运行。手机可能会丢失所有电池电量,应用程序可能无法运行......等等。

但这只是一个逻辑问题......如果您想在每天的特定时间后刷新数据,您应该只在UserDefaults中存储最后一次刷新时间,如果该时间超过了您所需的到期时间(在这种情况下24小时)然后刷新数据并更新上次更新的时间。

因此,如果您有活跃用户,只要24小时时差到期,它就会刷新,或者如果用户手机关闭了几天(无论出于何种原因),您的应用仍会知道需要刷新用户返回应用程序后的数据。

编辑:添加了代码示例

class RefreshManager: NSObject {

    static let shared = RefreshManager()
    private let defaults = UserDefaults.standard
    private let defaultsKey = "lastRefresh"
    private let calender = Calendar.current

    func loadDataIfNeeded(completion: (Bool) -> Void) {

        if isRefreshRequired() {
            // load the data
            defaults.set(Date(), forKey: defaultsKey)
            completion(true)
        } else {
            completion(false)
        }
    }

    private func isRefreshRequired() -> Bool {

        guard let lastRefreshDate = defaults.object(forKey: defaultsKey) as? Date else {
            return true
        }

        if let diff = calender.dateComponents([.hour], from: lastRefreshDate, to: Date()).hour, diff > 24 {
            return true
        } else {
            return false
        }
    }
}

你真的不必像我一样把它变成一个新的类或单身。为了答案,更容易保持所有内容。

因此,如果没有刷新日期,或者自上一个小时数大于24小时后,它将更新数据并更新上次刷新日期/时间。使用完成后,它还将返回是否更新数据。

您还可以在此处添加一个检查,如果需要,当天的当前小时为>= 16

编辑2:用户可选择的小时

private func isRefreshRequired(userPickedHour: Int = 16) -> Bool {

    guard let lastRefreshDate = defaults.object(forKey: defaultsKey) as? Date else {
        return true
    }

    if let diff = calender.dateComponents([.hour], from: lastRefreshDate, to: Date()).hour,
        let currentHour =  calender.dateComponents([.hour], from: Date()).hour,
        diff >= 24, userPickedHour <= currentHour {
        return true
    } else {
        return false
    }
}  

在此修改后的isRefreshRequired函数中,您可以传递一小时的值,并查看自上次刷新后是否至少24小时,以及当前小时是否大于用户所选小时。

这并不意味着顺便说一下它会说比如16:00。它将在用户加载该屏幕并且规则通过时运行(最少24小时过去,currentHour是&gt; = userSelected小时)

编辑3:如何致电

class ViewController: UIViewController {

    let refreshManager = RefreshManager.shared

    override func viewDidLoad() {
        super.viewDidLoad()

        refreshManager.loadDataIfNeeded() { success in
            print(success)
        }
    }
}

编辑:更改了逻辑

if let diff = calender.dateComponents([.day], from: lastRefreshDate, to: Date()).day,
    let currentHour =  calender.dateComponents([.hour], from: Date()).hour,
    diff >= 1, userPickedHour <= currentHour {
    return true
} else {
    return false
}

答案 1 :(得分:0)

您无法在iOS中使用长时间运行的计时器。事实上,您无法让您的应用在一天的特定时间拨打电话。

用户在短时间内锁定手机并暂停您的应用以节省电池电量。

除非你为越狱手机写作,否则没有办法做你要做的事。

编辑:

你说&#34;我只是想在用户在特定时间之后打开应用程序时看到该表视图数据被删除。&#34;

  

好的,那是不同的。当应用程序打开时,计算您希望删除记录的日期。

将该日期保存到UserDefaults。然后实现applicationDidBecomeActive()方法,并在该方法中,从UserDefaults中读取保存的日期,如果已通过,则删除您在表视图中显示的数据。

答案 2 :(得分:0)

简单样本

例如,我们可以在“ lastRefresh”中设置下一个更新日期,因此,当该日期过去时,它将再次刷新它,并为下一次刷新设置日期。

class RefreshManager: NSObject {

static let shared = RefreshManager()
private let defaults = UserDefaults.standard
private let defaultsKey = "lastRefresh"
private let calender = Calendar.current

func loadDataIfNeeded(completion: (Bool) -> Void) {
    if isRefreshRequired() {
        var date = Date()
        
        //Check for duration (Daily, Weekly or Monthly) (0,1,2)
        switch SaveManager.shared.user()!.UserShare.duration {
        case 0:
            //If user want to share daily
            date = date.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 1, weeks: 0, months: 0, years: 0)
            break
            
        case 1:
            //If user want to share weekly
            date = date.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 1, months: 0, years: 0)
            break
            
        case 2:
            //If user want to share monthly
            date = date.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 0, weeks: 0, months: 1, years: 0)
            break
            
        default:
            //If user want to share daily : Default
            date = date.addComponentsToDate(seconds: 0, minutes: 0, hours: 0, days: 1, weeks: 0, months: 0, years: 0)
            break
        }

        date = date.startOfDay
        defaults.set(date, forKey: defaultsKey)
        print(date.toString())
        
        completion(true)
    } else {
        completion(false)
    }
}

private func isRefreshRequired() -> Bool {
    guard let lastRefreshDate = defaults.object(forKey: defaultsKey) as? Date else {
        return true
    }
    
    if lastRefreshDate.isLaterThanOrEqualTo(date: Date()) {
        return true
    } else {
        return false
    }
}}