2

I'm developing an iOS App using Swift 3, and I need to run a code that clears the local database used at a certain time (let's say 1:00 AM everyday).

I came across this example for running a code at a given time, but the example he gave used a time interval from when the code is ran. Here's a modified version of the code posted:

func setAlarm(){
    print("set alarm called")
    let date = Date().addingTimeInterval(5 * 60 * 1)
    let timer = Timer(fireAt: date, interval: 0, target: self, selector: #selector(self.clearAllData), userInfo: nil, repeats: false)
    RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
}

This code will call my clearAllData function 5 minutes after the function setAlarm() code is called. This works just fine but it's not what I want. I want to be able to set an alarm that will go off at a certain time, not after N number of seconds.

How can I do that?

halfer
  • 19,824
  • 17
  • 99
  • 186
Razgriz
  • 7,179
  • 17
  • 78
  • 150

2 Answers2

5

I had done an iOS App like this, Searched a lot at last i used local notification. Delayed notification showing time . try this and let me know the results

`func scheduleNotification(date:String , time: String , subject:String) {

    var dateString = date+" "+time
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd-MM-yyyy HH:mm"

    let convertedDate = dateFormatter.date(from: dateString)!

    let subtractTime = Calendar.current.date(byAdding: .minute, value: -10, to: convertedDate)

    dateString = dateFormatter.string(from: subtractTime!)

    var localTimeZoneName: String { return TimeZone.current.identifier }
    var secondsFromGMT: Int { return TimeZone.current.secondsFromGMT() }
    dateFormatter.timeZone = TimeZone(secondsFromGMT: secondsFromGMT)
    dateFormatter.dateFormat = "dd-MM-yyyy HH:mm"

    let dateObj:Date = dateFormatter.date(from: dateString)!

    print("alaram time  : \(dateObj)")

    let triggerDaily = Calendar.current.dateComponents([.day,.month,.year,.hour,.minute,], from: dateObj)


    let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDaily, repeats: true)

    let alarmId = UUID().uuidString

    let content = UNMutableNotificationContent()
    content.title = "your title"
    content.body = subject
    content.sound = UNNotificationSound.init(named: "your sound filename.mp3")
    content.categoryIdentifier = alarmId

    let request = UNNotificationRequest(identifier: alarmIdentifier, content: content, trigger: trigger)

    print("alarm identi   : \(alarmIdentifier)")

    UNUserNotificationCenter.current().delegate = self
    UNUserNotificationCenter.current().add(request) {(error) in

        if let error = error {
            print("Uh oh! i had an error: \(error)")
        }
    }
}`   

the above func is to set notification

func playSound(_ soundName: String) {

    //vibrate phone first
    AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
    //set vibrate callback
    AudioServicesAddSystemSoundCompletion(SystemSoundID(kSystemSoundID_Vibrate),nil,
                                          nil,
                                          { (_:SystemSoundID, _:UnsafeMutableRawPointer?) -> Void in
                                            print("callback", terminator: "") //todo
    },
                                          nil)
    let url = URL(
        fileURLWithPath: Bundle.main.path(forResource: soundName, ofType: "mp3")!)

    var error: NSError?

    do {
        audioPlayer = try AVAudioPlayer(contentsOf: url)
    } catch let error1 as NSError {
        error = error1
        audioPlayer = nil
    }

    if let err = error {
        print("audioPlayer error \(err.localizedDescription)")
    } else {
        audioPlayer!.delegate = self
        audioPlayer!.prepareToPlay()
    }
    //negative number means loop infinity
    audioPlayer!.numberOfLoops = -1
    audioPlayer!.play()
}

to play sound pass your mp3 file name also declare audioPlayer as AVAudioPlayer

playSound("Your sound file name")

    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: UIAlertControllerStyle.actionSheet)
    actionSheet.view.tintColor = UIColor.black

    actionSheet.addAction(UIAlertAction(title: "Stop Alert", style: UIAlertActionStyle.default, handler: { (alert:UIAlertAction!) -> Void in


        self.audioPlayer?.stop()
    }))
    window?.rootViewController!.present(actionSheet, animated: true, completion: nil)

add these code in UNUserNotificationCenterDelegate methods also want to import AudioToolBox and AVFoundation

2

As far as I know, this cannot be done due to background mode restrictions in iOS. Refer Background modes. As long as your app doesn't fall under these, you cannot ask your code to fire at a particular time of the day(or night).

I'm assuming that your app wont be present in the foreground(based on the 1 am time)

As a work around, you can launch a local notification at the said time asking the user to clear the data on tap of the local notification.(seems stupid though)

Or if your app does support the above modes, you can check this answer.

Alejandro Vargas
  • 1,327
  • 12
  • 26