I am nearly new to swift Xcode and I am building an app, when the end user is near a iBeacon hi will get a local push notification.The problem I have is each time he comes near to it(if he got back and forward he will get each time he is near).
So I think to limit by time like 5 minuets of some like that.
I can not find in Swift how to limit a function to run in a time limit.(like 5 minutes)
Can some one point me in the correct direction?
Thanks for the help.
I did try to work with a timer but it did not do the job for me.
You Can create a Variable: beaconsHasBeenRecognized to turn to true when the beacon has been recognized, then the next time user goes back and forth, before triggering notification, your code should evaluate it beaconsHasBeenRecognized,its false, otherwise, if it is true, it will not trigger the notification.
Then with the timer, at the moment you set beaconsHasBeenRecognized to true, you start a timer to change beaconsHasBeenRecognized to false within the time that you want, like the 5 minutes.
Related
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.
I am facing some problem in background service.I have registered the backgrond service like:var service = Ti.App.iOS.registerBackgroundService({url:'/bgservice.js'});
in bgservice.js :I actually want to check the DB(where the data execution time is>8mins) and trigger local notification.But it is not working.So tried a sample first like this,to see how much time the app is active in background:
var timer = setInterval(startsampletest, 6000);
startsampletest();
function startsampletest(){
count=count+1;
Ti.API.info("1.!!!!!*******startsampletest is called for"+count);
}
which gives me only 5 times every 6 seconds so it is executing only for 30 min(please correct me if I am wrong)But in axway documentation it says the bgservice will be active for 10 mins.
Can anyone pls help me on this.I want the app to be active in background for 10 mins.pls let me know if I have made any mistakes.
It is not guaranteed that a background task created by Ti.App.iOS.registerBackgroundService() will run up to 10 minutes,
see: https://titaniumsdk.com/api/titanium/app/ios/backgroundservice.html#background-service-limitations
... typically to no more than 10 minutes.
But more crucial is that
The OS may terminate the background service at any point to reclaim resources.
For longer background tasks under iOS you have to use
the Ti.URLSession module (com.appcelerator.urlSession).
In general, see https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_How-tos/Platform_API_Deep_Dives/iOS_API_Deep_Dives/iOS_Background_Services.html
To provide some context, the application I'm working on allows the user to record a series of events along a timeline. One important piece of feedback we received from beta testers was that when the user exits the app while recording they'd like the timer to keep up to date for a set amount of time.
For example if the user has recorded 5 minutes and then leaves the app to check an email for 20 seconds, the timer should be 5:20, but it was actually still 5 minutes.
So we've fixed that - the app now would now show 5:20, and this works in the background.
However we can't figure out a way to stop it after a certain amount of time. A user might want the timer to resume if the app is in the background for a short amount of time, but if you leave it in the background for 30 minutes, the timer will update, and I'd like to be able to give the users an optional cut-off time so that the app pauses after a set amount of time.
I've tried listening out for UIApplicationDelegate notifications, but the problem is I'm looking for a point between applicationDidEnterBackground: and applicationWillTerminate, but there's sadly nothing to cater for my needs there.
To summarise, I'd like to have a grace period of 30-60 seconds from applicationWillResignActive: to determine whether or not to pause the timer, or let it keep going.
Would this be possible?
Thanks in advance
It's generally a bad idea to assume your app will be running in the background.
A better way to think about it IMO would be to set a variable to the current time in applicationDidEnterBackground: and check the time interval to now in applicationWillBecomeActive: :
If the interval is bigger that your grace period, have the time backup to when the app was paused.
If it is smaller, update it as if the app was never in the background.
Use dispatch_after to execute a block of code after a certain number of second:
int64_t delay = 30.0; // In seconds
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0ull), ^(void){
//DO SOMETHING
});
Swift 3.0 Xcode 8.0 Code sample:
Using delegate methods : applicationWillBecomeActive & applicationWillResignActive to capture the time in between.
OR
let deadlineTime = DispatchTime.now() + .seconds(30)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
alert.dismiss(animated: true, completion: nil)
}
Hope this helps.
I am developing a phonegap application that sends the current GPS location to a server. In order to do so, we have the following code fragment:
navigator.geolocation.watchPosition(gpsTracker.onNewCoordinates, gpsTracker.onError, {
enableHighAccuracy : true,
maximumAge: 4000, //should be default, just in case
timeout: 5000
});
The callback functions take care of submitting the results. On our Android test-device this functionality is working just nicely. However when we run the same code on an iOS device it usually does nothing, except when the GPS reception is fine it will send two coordinates and then it stops.
It looks like iOS only obtains some information once, and never triggers the callback functions when there are new coordinates available.
Anyone with similar experience / solution to this problem?
I solved my issue as follows. It turns out that navigator.geolocation.watchPosition does not seem to work well on iOS. I rewrote the code using a javascript setInterval which invokes getCurrentPosition every 5 seconds instead:
navigator.geolocation.getCurrentPosition( gpsTracker.onNewCoordinates, gpsTracker.onError, {
enableHighAccuracy : true,
maximumAge: 4000, // should be default, just in case
timeout: 5000
});
Now the GPS position is correctly returned every 5 seconds.
Have a look at this:
http://groups.google.com/group/phonegap/browse_thread/thread/58f7ff98170b16c4
There is something written about geolocator.start() and stop(), preserved for iOS. Maybe this helps?
According to my experience, the GPS must be "hot" in order to deliver valid positions, i.e. it must be given enough time to connect to satellites etc. Usually, you have it "hot" only if you start watching, not if you just pick single positions. On my HTC, values gained by getCurrentPositions() have therefore turned out too unprecise (related to a near scope, e.g. within 50m). So it might be the right way to try once more to find a solution with startWatching().
Suppose I use QTPs recovery scenario manager to set the playback synchronization timeout to 0. The handler would return with "continue with next statement".
I'd do that to make sure that any following playback statements don't waste their time waiting for the next non-existing/non-matching step before failing:
I have a lot of GUI tests that kind of get stuck because let's say if 10 controls are missing, their (consecutive) playback steps produce 10 timeout waits before failing. If the playback timeout is 30 seconds, I loose 10x30 seconds=5 minutes execution time while it really would be sufficient to wait for 30 seconds ONCE (because the app does not change anymore -- we waited a full timeout period already).
Now if I have 100 test cases (=action iterations), this possibly happens 100 times, wasting 500 minutes of my test exec time window.
That's why I come up with the idea of a recovery scenario function setting the timeout to 0 after/upon the first failed playback step. This would accelerate the speed while skipping the rightly-FAILED step, yet would not compromise the precision/reliability of identifying the next matching GUI context (which creates a PASSED step).
Then of course upon the next passed playback step, I would want to restore the original timeout value. How could I do that? This is my question.
One cannot define a recovery scenario function that is called for PASSED steps.
I am currently thinking about setting a method function for Reporter.ReportEvent, and "sniffing" for PASSED log entries there. I'd install that method function in the scenario recovery function which sets timeout to 0. Then, when the "sniffer" function senses a ReportEvent call with PASSED status during one of the following playback steps, I'd reset everything (i.e. restore the original timeout, and uninstall the method function). (I am 99% sure, however, that .Click and .Set methods do not call ReportEvent to write their result status...so this option might probably not work.)
Better ideas? This really bugs me.
It sounds to me like you tests aren't designed correctly, if you fail to find an object why do you continue?
One possible (non recovery scenario) solution would be to use RegisterUserFunc to override the methods you are using in order to do an obj.Exist(0) before running the required method.
Function MyClick(obj)
If obj.Exist(1) Then
obj.Click
Else
Reporter.ReportEvent micFail, "Click failed, no object", "Object does not exist"
End If
End Function
RegisterUserFunc "Link", "Click", "MyClick"
RegisterUserFunc "WebButton", "Click", "MyClick"
''# etc
If you have many controls of which some may be missing and you know that after 10 seconds you mentioned (when the first timeout occurs), nothing more will show up, then you can use the exists method with a timeout parameter.
Something like this:
timeout = 10
For Each control in controls
If control.exists(timeout) Then
do something with the control
Else
timeout = 0
End If
Next
Now only the first timeout will be 10 seconds. Each and every subsequent timeout in your collection of controls will have the timeout set to 0 which will save your time.