Control location manager update interval - location

Is there a way to control the update interval of the location manager? I used the nearest 10 meter setting for accuracy but it appears that my application gets one update every second, which I think is too often. I want the good accuracy but not the frequency.
Thanks.

I did it with a timer:
in the header add:
ServerInterface *serverInterface;
in the .m file:
- (void)viewDidLoad
{
...
[frequentLocationUpdateTimer invalidate];
frequentLocationUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:
#selector(reEnableLocationTick:) userInfo:nil repeats:YES];
...
}
- (void)reEnableLocationTick:(NSTimer *)theTimer
{
[locationGetter startUpdates]; //Maybe you have to change this line according to your code
}
and in your locationmanager...:
- (void)locationManager:(CLLocationManager *)manage didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
...
if (newLocation.horizontalAccuracy < 100)
{
[locationManager stopUpdatingLocation];
}
...
// let our delegate know we're done
[delegate newPhysicalLocation:newLocation];
}
The code simply stops updating the location after reaching a minimum accuracy of 100m. Then, every 30sec a timer reenables the locationmanager again.

Related

How to avoid asynchronous nature of scrollToVisibleRect causing intermittent timing issues

I am writing a Cocoa UI and am calling NSView's scrollRectToVisible repeatedly in a short space of time as a result of the user holding down a certain key (and hence repeatedly firing events on the main queue).
Through logging I can see that successive keyDown() events are firing prior to the scrollRectToVisible having completed its prior changing of the visibleRect. This is resulting in the subsequent scrollRectToVisible being called with incorrect inputs (namely the wrong starting visibleRect) and is leading to non-sensical UI behaviour. This happens about 50% of the time which I guess is to be expected dealing with an asynchronous problem.
How can I address this?
One way I can think of is by somehow turning scrollRectToVisible into a synchronous call. The problem is that it is an AppKit API and the method returns immediately with a boolean indicating whether it is going to scroll or not.
Try putting the code in the view that responds to the -keyDown:.
This example controls the scrolling with a timer instead of the repeated keyDowns from holding the key.
I couldn't get the UI unwanted behavior, so I don't know if this will help.
- (BOOL)acceptsFirstResponder {
return YES;
}
- (BOOL)canBecomeKeyView {
return YES;
}
- (void)keyDown:(NSEvent *)theEvent {
if (timer == nil) {
timer = [NSTimer scheduledTimerWithTimeInterval:0.01
target:self
selector:#selector(doScroll:)
userInfo:nil
repeats:YES];
}
NSLog(#"event %# with Timer%#", theEvent, timer);
}
- (void)keyUp:(NSEvent *)theEvent {
[timer invalidate];
timer = nil;
NSLog(#"keyUp timer:%#", timer);
NSLog(#"event %#", theEvent);
}
- (void)doScroll:theTimer {
NSEvent * current = [NSApp currentEvent]; //use this to parse
NSLog(#"current press %#", current);
[self scrollRectToVisible:NSMakeRect(self.visibleRect.origin.x + 10,
self.visibleRect.origin.y + 10,
self.bounds.size.width,
self.bounds.size.height)];
}

How to play mp3 file remotely on server without blocking UI in ios

I am working on iOS app let me play mp3 file from url. It works fine once loaded.The problem is it takes about 30 seconds to load and blocks UI from transition to other view controller.
code:
I am using AVAudioPlayer class and here are my settings.
(void)setupAudioPlayer:(NSString*)fName
{
// calls and pass url name to MyAudioPlayer class method
[self.audioPlayer initWithData:fName];
self.currentTimeSlider.maximumValue =
[self.audioPlayer getAudioDuration];
//init the current time display and the labels.
//if a current time was stored
//for this player then take it and update the time display
self.timeElapsed.text = #"0:00";
self.duration.text = [NSString stringWithFormat:#"-%#",
[self.audioPlayer timeFormat:
[self.audioPlayer getAudioDuration]]];
}
then call above method and pass the url as "http://www.test.com/test1.mp3"
(void)viewDidLoad
{
[super viewDidLoad];
self.audioPlayer = [[MyAudioPlayer alloc] init];
//pass the url where mp3 located i.e http://www.test.com/test.mp3
[self setupAudioPlayer:self.urlStr];
}
then, it play when button below pressed.
- (IBAction)playAudioPressed:(id)playButton
{
[self.timer invalidate];
//play audio for the first time or if pause was pressed
if (!self.isPaused) {
//start a timer to update the time label display
self.timer =
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(updateTimer:)
userInfo:nil
repeats:YES];
[self.audioPlayer playAudio];
self.isPaused = TRUE;
} else {
[self.audioPlayer pauseAudio];
self.isPaused = FALSE;
}
}
As I mentioned earlier the problem is loading for very long and blocking UI. Please help or suggest me with how to decrease loading time and avoid blocking ui.
any help will be very appreciated.
Thank you
Here is my code for the STREAMING of a remote mp3 file:
#import AVFoundation;
...
#property (nonatomic, retain) AVPlayer *objAVPlayer;
#property (nonatomic, getter=isPlaying) BOOL playing;
// in viewDidLoad
_objAVPlayer = [AVPlayer playerWithURL:[NSURL URLWithString:#"http://www.asdasd.com/file.mp3"]];
...
- (void)playPressed {
if([self isPlaying]) {
_playing = false;
[_objAVPlayer pause];
} else {
_playing = true;
[_objAVPlayer play];
}
}
A possible time delay can be due to a slow connection. I hope this can help you.

NSTimer is not firing the scheduled method

My code is given below.I am trying to show a counter on the screen in a window and enable a button after count limit is over.
When I run the code before nstimer and after nstimer are printed only once and nothing is printed from the time countdown function.Someone pelase help me.
- (void)startTimer:(NSInteger)count;
{
NSLog(#"Entered the start timer function");
self.countLimit = count;
[self.lbCount setStringValue:[NSString stringWithFormat:#"%ld",self.countLimit]];
NSLog(#"Before nstimer");
#try{
self.timeCounter = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timeCountDown) userInfo:nil repeats:YES];
}
#catch (NSException* e) {
NSLog(#"%#",[e description]);
}
NSLog(#"After nstimer");
}
- (void)timeCountDown
{
NSlog(#"Entered the function");
self.countLimit = self.countLimit - 1;
NSLog(#"Just entered the function time countdown");
if (self.countLimit < 0) {
NSLog(#"Entered count limit less than 0");
[self.timeCounter invalidate];
self.timeCounter = nil;
[self.btContinue setEnabled:YES];
return;
}
[self.lbCount setStringValue:[NSString stringWithFormat:#"%ld",self.countLimit]];
}
As detailed in the API docs, your scheduled method must take a NSTimer * parameter:
- (void)timeCountDown:(NSTimer *)timer
Don't forget to change your selector in the scheduledTimerWithTimeInterval call to reflect this:
// There's a colon after selector name to denote
// the method takes one parameter
self.timeCounter = [NSTimer scheduledTimerWithTimeInterval:1
target:self selector:#selector(timeCountDown:) userInfo:nil repeats:YES];
If you don't want to pass as a arguement NSTimer* then use below after your timer
[self.timeCounter fire];

XCode View Controller Not Updating in Do Loop

I have a do loop that I want to execute a command every 1 second while a SWITCH is on.
The Code works fine ONCE, when I don't have the DO LOOP.
However, as soon as I add the LOOP, none of the labels in the view controller are updated, the back button for the storyboard doesn't work, and the SWITCH will not toggle off. Essentially, the DO LOOP keeps looping, but nothing on the screen will work, nor can I back out.
I know I'm doing it wrong. But, I don't now what. Any thoughts would be appreciated.
I attached the code that gets me in trouble.
Thanks,
- (IBAction)roaming:(id)sender {
UISwitch *roamingswitch = (UISwitch *)sender;
BOOL isOn = roamingswitch.isOn;
if (isOn) {
last=[NSDate date];
while (isOn)
{
current = [NSDate date];
interval = [current timeIntervalSinceDate:last];
if (interval>10) {
TheCommand.text=#"ON";
[self Combo:sendcommand];
last=current;
}
}
}
else
{
TheCommand.text=#"OFF";
}
}
iOS and OSX are event based systems and you cannot use loops like this in the main (UI) thread to do what you want to do, otherwise you don't allow the run loop to run and events stop being processed.
See: Mac App Programming Guide section "The App’s Main Event Loop Drives Interactions".
What you need to do is set-up a timer (NSTimer) which will fire every second:
.h file:
#interface MyClass : NSView // Or whatever the base class is
{
NSTimer *_timer;
}
#end
.m file:
#implementation MyClass
- (id)initWithFrame:(NSRect)frame // Or whatever the designated initializier is for your class
{
self = [super initInitWithFrame:frame];
if (self != nil)
{
_timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
return self;
}
- (void)dealloc
{
[_timer invalidate];
// If using MRR ONLY!
[super dealloc];
}
- (void)timerFired:(NSTimer*)timer
{
if (roamingswitch.isOn)
{
TheCommand.text=#"ON";
[self Combo:sendcommand];
}
}
#end
Give your processor enough time to update your view controller and not be interrupted by other processes. I give it 0.5 second before and after the view controller update signal.
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
self.CrashingTime.text = [NSString stringWithFormat: #"Crash Time = %f ms", outputOfCrashTime];
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];

NSTimer invalidate - duplicate timers

A simplified set of methods to demonstrate what's happening:
- (void)timerDidFire {
NSLog(#"fire");
}
- (void)resetTimer:(NSTimer *)timer {
if (timer) [timer invalidate]; // timer = nil; here doesn't change anything
NSLog(#"%#", timer);
timer = [NSTimer ...Interval:1 ... repeats:YES];
}
- (IBAction)pressButton {
[self resetTimer:myTimer];
}
Clearing I'm doing something wrong, but what? Why do I get an extra timer with every press?
Each time the resetTimer: method is called you create a new NSTimer instance. Unfortunately after the execution of this method is finished you lost all your references to the new instance because it was assigned to a local variable.
The timer you create inside the method is not assigned to the myTimer variable. Whatever myTimer is, it is not the new created timer.
You could dump all those local variables and simply use something like this:
- (void)resetTimer {
[myTimer invalidate]; // calls to nil are legal, so no need to check before calling invalidate
NSLog(#"%#", myTimer);
myTimer = [NSTimer ...Interval:1 ... repeats:YES];
}
- (IBAction)pressButton {
[self resetTimer];
}

Resources