Local time was changed event (get change amount) - ios

With the lines below it is possible to get a notification on app launch that the system clock (local device time) was changed by the user.
NotificationCenter.default.addObserver(self, selector: #selector(TimeWasChanged), name: NSNotification.Name.NSSystemClockDidChange, object: nil)
#objc func TimeWasChanged(){
print("time was changed by the user!")
}
I'm wondering if there is also a way to get notified about the amount the time value was changed (e.g. clock set +10 minutes from 8:20pm to 8:30pm).
If theres nothing like this already implemented would it be possible to calculate this offset manually (without using internet --> No NHC or JSON)?
Help would be very appreciated, Jane

Related

iOS: OperationQueue.schedule(after: Date) that cannot be triggered by date change

Problem
I need to get a callback when at least X amount of time has passed since the date for the callback has been set.
Example 1:
This would have worked great, but it's possible to trigger an execution of the block by setting the date earlier than the correct time right now:
let responseDate = Date().advanced(by: 60) // 1 min
OperationQueue.current.schedule(after: .init(responseDate), {
print("the time is now!") // possible to set the current date 1 min before
}
On the other hand, the solution for getting a current uptime from this answer works great, but it requires timer constantly running to check if we're close to date.
Is it possible to combine these two approaches and somehow "attach" a callback to KERN_BOOTTIME, so that the OS will call my method when the boottime reaches a certain value?
I'm looking as well to alternative engineering solutions that satisfy two criterias:
It should not be possible to trigger the callback by resetting the device date to some arbitrary value in the past
If the device has been put to sleep (e.g. by pressing the on/off side button), the clock should still be "ticking", so that the method will be called back while the app is running in the background.
More details:
Backgrounding / app termination is out of scope
The main point is to prevent a bypass by switching the date backwards in the settings.

How to observe 'boldTextStatusDidChangeNotification' using default notification center in Swift 5

I'm trying to have observe running constantly in the app background which will trigger custom action if Accessibility Bold Text feature has been enabled via Mobile Device Settings.
My understanding is I need to add observe to the default notification center and the name of the notification is 'boldTextStatusDidChangeNotification'.
Can someone advice on the code sample for this?
You can check the state of many accessibility options thanks to a bunch of events provided by the system.
Add an observer as follows:
NotificationCenter.default.addObserver(self,
selector: #selector(methodToBeCalled(notification:)),
name: UIAccessibility.boldTextStatusDidChangeNotification,
object: nil)
... and create the method to be fired when the appropriate event occurs:
#objc private func methodToBeCalled(notification: Notification) {
//Create your actions here.
}
If you want further information or check a complete list of these events with code snippets, I suggest to take a look at this site. 👍

How to limit number of requests to a database

I have an app with a settings page where the settings of each user are stored in a MySQL database. I was wondering what is the best way to update the database for every setting the user changes while sending the minimal number of requests as I'm worried that it will crash if it sends too many( it has happened before).
I was thinking about setting a timer for ~5 seconds when the user first changes a setting, and then reset the timer to 5 seconds again if another setting is changed. Once that timer is finished it will send a request to the server to update all the settings at once. It would also constantly store the new values locally to the app, so if the user closes the app before the 5 seconds are up it will send the request once/if the app loads up again.
Is this viable/what's the best way to go about this?
You need to make some logic functions in your app, so i will try make an pseudo codes below. Hope it will give you an idea. I don`t know the MySQL details but i am trying to explain native Swift way.
First of all you should fetch data partly, I mean if you try to fetch all data at the same time your app can work very slow.. That is why we are doing pagination in the app.
As well as pagination you want to refresh the data fresh 5 seconds so i will use Timer object, which will trigger every 5 seconds the API function and catch data based on pagination. Check your below codes and implement step by step to your project. Happy Coding.
var timer: Timer?
func scheduledTimerWithTimeInterval(){
// Scheduling timer to Call the function "loadNewDataAutomatically" with the interval of 5 seconds
timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(self.loadNewDataAutomatically), userInfo: nil, repeats: true)
}
#objc func loadNewDataAutomatically(_ pageNumber: Int, _ pageSize: Int, onSuccess: ((Bool) -> Void)?, onError: ((Error) -> Void)?){
// Call your api here
// Send true in onSuccess in case new data exists, sending false will disable pagination
// If page number is first, reset the list
if pageNumber == 1 { self.list = [YourDataModel]() }
// else append the data to list
self.list.append(apiResponseList)
// If Api responds with error
onError?(apiError)
// Else end success with flag true if more data available
let moreDataAvailable = !apiResponseList.isEmpty
onSuccess?(moreDataAvailable)
}
Assuming that the Database (MySQL) is on a server
You can try using WorkManager for this requirement.
When the user changes their settings, save them locally (which you are already doing)
enqueue a Unique Periodic Work Request using WorkManager & set up the time at what interval should the response be sent to the server.
Minimum time interval is around 15 min. but not guaranteed at exactly 15 minutes,
the system fires it when it seems fit, also according to the Constraints that you set on your Work Request.
You can also use a OneTimeWorkRequest, if you don't need periodic, with an Initial Delay of whatever time you need.
Edit: This question was later edited and ios, swift tags were added where previously it was for android.
If anyone comes here searching for something similar for Android, this would work.

Observe battery out of charge, Swift

I want to execute some code when iPhone battery iPhone run out of battery.
Will func applicationWillTerminate(_ application: UIApplication) { be called? If no then does exist any other way to track this? Thanks in advance.
There is no support for this instead you have to decide when the battery level is so low that you need to run your code.
What you can do is listen to the notification batteryLevelDidChangeNotification which is done by activating monitoring see isBatteryMonitoringEnabled
Like mentioned in the documentation the notifications are sent no more than once per minute so you have to determine a battery level that is low enough to be considered as almost depleted and then execute the code.
I have no idea what this could be, from personal experience I have seen my phones stay alive a long time on values under 5% but also seen them die shortly after going below 10%
You can use the following code snippet:
func startObservingBatteryDrainage(){
if UIDevice.current.isBatteryMonitoringEnabled && (UIDevice.current.batteryState == .unplugged || UIDevice.current.batteryState == .unknown){
if UIDevice.current.batteryLevel < 0.1{
NotificationCenter.default.addObserver(self, selector: #selector(funcWhenBatteryIsAlmostDrained), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}
}
}
#objc func funcWhenBatteryIsAlmostDrained(){
//do stuff
}

How can I run a method after n minutes I received a geofence event in iOS?

I'm working on a Geofence based iOS application and I would to know when the user stays more than 5 minutes inside a place.
Now, the geofence part is already done and working, I get the "enter" and "exit" events, but I want to execute some methods 5 minutes after I entered in a geofenced area, if I don't left it.
The main problem here is that NSTimers will not work with the app closed and I don't know how to focus this.
Any ideas?
Thank you for your time!
P.S: CLVisit class is not valid on this case because the events for this class are not "in real time" and we cannot set a time-inside.
You can use NSTimer when your app is Active like this :
let timer = NSTimer(timeInterval: 1.0, target: self, selector: #selector(self.printStr), userInfo: nil, repeats: true)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
and also if your app did receive UIApplicationWillTerminateNotification event you can save the current date to e.g userDefaults and use it after the user run the application again. Another way is to use UILocalNotification after you receive AppWillTerminate event, you should schedule the UILocalNotificaiton and trigger it after 5 minutes.
Hope it helps you

Resources