Objective C: function in sceneDidEnterBackground not running - objective-c

I am testing out a NSTimer with selector in sceneDidEnterBackground, but the selector does not run when I press the home button once. I am trying to run a timer when the home button is pressed once. Does anyone know what is wrong? This is my code in SceneDelegate.m
- (void)sceneDidEnterBackground:(UIScene *)scene {
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector:#selector(test)
userInfo: nil repeats:NO];
// NSLog(#"test"); //it prints out "test" here
[(AppDelegate *)UIApplication.sharedApplication.delegate saveContext];
}
- (void) test{
NSLog(#"test");
}

Related

How do I set a NSTimer to stop if a certain action is running?

I have a popup in a custom view controller that is presented after 1 minute thanks to my NSTimer.
My NSTimer code:
[NSTimer scheduledTimerWithTimeInterval:60.0f
target:self selector:#selector(methodB:) userInfo:nil repeats:YES];`
The method that reveals the popup
- (void) methodB:(NSTimer *)timer
{
//Do calculations.
[self showPopupWithStyle:CNPPopupStyleFullscreen];
}
I'm trying to set the NSTimer to stop running if the [self showPopupWithStyle:CNPPopupStyleFullscreen]; is currently open, running or active.
Then I would like to start the NSTimer back up again if the popup view controller is NOT open, running or active.
Any help, samples or examples would be greatly appreciated!
My project is written in Objective-C.
EDIT:
I tried the answers in the suggested "possibly similar" answer and it doesn't seem to work for what I am doing. How do I stop NSTimer?
This seems to do the trick.
#property (nonatomic, strong) CNPPopupController *popupController;
- (void)_timerFired:(NSTimer *)timer;
#end
NSTimer *_timer;
- (void)viewDidLoad {
[super viewDidLoad];
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
}
}
- (void)_timerFired:(NSTimer *)timer {
if ([_timer isValid]) {
[self showPopupWithStyle:CNPPopupStyleFullscreen];
[_timer invalidate];
}
_timer = nil;
NSLog(#"ping");
}
If you want to restart the timer just add this code where you'd like the action to start back up.
if (!_timer) {
_timer = [NSTimer scheduledTimerWithTimeInterval:10.0f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
}
Hope this helps! :)

Fire IBAction automatically

I have a button and want to fire it automatically by itself without touch.
Is it possible?
-(IBAction)xxx:(id)sender
My answer assumes you have the method:
- (IBAction)someAction:(UIButton *)sender {
}
and that you have a reference to the button in an instance variable named someButton.
If you just need to "fire it" now, simply call it:
[self someAction:someButton];
If you need to "fire it" once, but later, you can do:
// call it 5 seconds from now
[self performSelector:#selector(someAction:) withObject:someButton afterDelay:5.0];
If you want to fire it repeatedly, use a timer:
myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(buttonTimerFired) userInfo:nil repeats:YES];
- (void)buttonTimerFired {
[self someAction:someButton];
}
Action can be called like every regular function - you can do it by running a timer on something else.
You should use NSTimer for doing your work.
[NSTimer scheduledTimerWithTimeInterval: 0.01f target: self selector: #selector(BtoonMethod) userInfo: nil repeats: NO];
-(void)BtoonMethod
{
// write code for call yor button method
}

NSTimer causes "unrecognized selector" crash when it fires

I'm using a NSTimer to run an animation (for now just call it myMethod). However, its causing a crash.
Here's the code:
#implementation SecondViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void) myMethod
{
NSLog(#"Mark Timer Fire");
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"We've loaded scan");
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(myMethod:)
userInfo:nil
repeats:YES];
animationTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(myMethod:) userInfo:nil repeats: YES];
}
And here's the output during the crash
-[SecondViewController myMethod:]: unrecognized selector sent to instance 0x4b2ca40
2012-06-21 12:19:53.297 Lie Detector[38912:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SecondViewController myMethod:]: unrecognized selector sent to instance 0x4b2ca40'
So what am I doing wrong here?
I ran into this problem while using Swift. It may not be evident that in Swift I discovered that the target object of NSTimer must be an NSObject.
class Timer : NSObject {
init () { super.init() }
func schedule() {
NSTimer.scheduledTimerWithTimeInterval(2.0,
target: self,
selector: "myMethod",
userInfo: nil,
repeats: true)
}
func myMethod() {
...
}
}
Hope this helps somebody.
either you can use only
- (void)myMethod: (id)sender
{
// Do things
}
or you can do (remove : from both the method name)..
animationTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(myMethod) userInfo:nil repeats: YES];
hope this will help you
replace this
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(myMethod:)
userInfo:nil
repeats:YES];
by this
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(myMethod)
userInfo:nil
repeats:YES];
The timer's action method should take one argument:
- (void)myMethod: (NSTimer *)tim
{
// Do things
}
The name of this method is myMethod:, including the colon. Your current method's name is myMethod, without the colon, but you create your timer by passing a method name that has it: selector:#selector(myMethod:).
Currently, then, the timer sends the message myMethod: to your object; your object doesn't respond to that (but would respond to myMethod) and raises an exception.

Using NSTimer to create a countdown

I have a int value representing a countdown to an event (view being displayed). Currently, i do this:
- (void) buttonTapped:(id)sender {
[self performSelector:#selector(displayView) afterDelay:countdownValue];
}
What I would like to do is the following...
When the button is tapped, change the tint colour of my navigation bar to red, yellow, green proportionally, until the countdown expires, then display the view.
So for example if my countdown is 3 seconds, one second for each colour, if it is 5 seconds, 1.666 for each colour.
Can I use an NSTimer to schedule this?
After the view is displayed the timer would need invalidating.
Thanks
float count_down = 5.0;
[NSTimer scheduledTimerWithTimeInterval: count_down*(1.0/3.0) target: self
selector: #selector(changeToRed:) userInfo: nil repeats: NO];
[NSTimer scheduledTimerWithTimeInterval: count_down*(2.0/3.0) target: self
selector: #selector(changeToGreen:) userInfo: nil repeats: NO];
[NSTimer scheduledTimerWithTimeInterval: count_down target: self
selector: #selector(changeToBlue:) userInfo: nil repeats: NO];
And callbacks (do whatever you want there):
-(void) changeToRed:(NSTimer*) t {
NSLog(#"red");
}
-(void) changeToGreen:(NSTimer*) t {
NSLog(#"green");
}
-(void) changeToBlue:(NSTimer*) t {
NSLog(#"blue");
}

UIButton Touch and Hold

I haven't found a very easy way to do this. The ways I've seen require all these timers and stuff. Is there any easy way I can hold a UIButton and cause it to repeat the action over and over until it gets released?
You can do the following: Make an NSTimer that will start up when the app starts or in viewDidLoad and also make a boolean.
For example:
//Declare the timer, boolean and the needed IBActions in interface.
#interface className {
NSTimer * timer;
bool g;
}
-(IBAction)theTouchDown(id)sender;
-(IBAction)theTouchUpInside(id)sender;
-(IBAction)theTouchUpOutside(id)sender;
//Give the timer properties.
#property (nonatomic, retain) NSTimer * timer;
Now in your implementation file (.m):
//Synthesize the timer
#synthesize timer;
//When your view loads initialize the timer and boolean.
-(void)viewDidLoad {
g = false;
timer = [NSTimer scheduledTimerWithInterval: 1.0 target:self selector:#selector(targetMethod:) userInfo:nil repeats: YES];
}
Now make an IBAction for "Touch Down" set the boolean to lets say true. Then make another IBAction button for "Touch Up Inside" and "Touch Up Outside" assign the boolean to false.
For example:
-(IBAction)theTouchDown {
g = true;
}
-(IBAction)theTouchUpInside {
g = false;
}
-(IBAction)theTouchUpOutside {
g = false;
}
Then in that NSTimer method, put the following:(assume g is the boolean you have declared)
-(void) targetmethod:(id)sender {
if (g == true) {
//This is for "Touch and Hold"
}
else {
//This is for the person is off the button.
}
}
I hope this simplifies everything... I know it still uses a timer but there is not another way.
Unfortunately, it still looks like you have to code this functionality for yourself. simplest way (You still need a timer though):
A function that performs the action you want to repeat:
-(void) actionToRepeat:(NSTimer *)timer
{
NSLog(#"Action triggered");
}
in your .h file declare and set a property for a timer:
#interface ClassFoo
{
NSTimer* holdTimer;
}
Then in the .m make two IBActions:
-(IBAction) startAction: (id)sender
{
holdTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:#selector(actionToRepeat:) userInfo:nil repeats:YES];
[holdTimer retain];
}
-(IBAction) stopAction: (id)sender
{
[holdTimer invalidate];
[holdTimer release];
holdTimer = nil;
}
Then Just link to the Touch Down event in IB from the button to startAction and the Touch Up Inside to the 'Stop Action'. It isn't a one liner but it allows you to customise the rate the action repeats as well as allowing you to trigger it from another outlet/action.
You might consider subclassing UIButton and adding this functionality if you are going to be using this functionality often - then it is only (slightly) painful to implement the first time.
An other way to use this NBTouchAndHoldButton. This is exactly what you want, and very easy to implement it:
TouchAndHoldButton * pageDownButton = [TouchAndHoldButton buttonWithType:UIButtonTypeCustom];
[pageDownButton addTarget:self action:#selector(pageDownAction:) forTouchAndHoldControlEventWithTimeInterval:0.2];
Good luck!
I cannot reply to the first one, but this line:
timer = [NSTimer scheduledTimerWithInterval: 1.0 target:self selector:#selector(targetMethod:) userInfo:nil repeats: YES];
for at least iOS 4.1 and newer needs to be:
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(targetMethod:) userInfo:nil repeats: YES];
I know this is an old question, but as an easy way, like to consider using "[NSObject performSelector:withObject:afterDelay:]" to repeatedly invoke methods in any particular time interval.
In this case:
NSTimeInterval someTimeInterval = 1;
- (IBAction)action:(id)sender {
UIButton * const button = sender;
if (button.state != UIControlStateHighlighted) {
return;
}
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:_cmd object:sender];
[self performSelector:_cmd withObject:sender afterDelay:someTimeInterval];
}