I have implemented automatic scrolling of UIPageViewController after every 5 seconds using timer like this:
_bannerTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(loadNextController)
userInfo:nil
repeats:YES];
- (void)loadNextController
{
self.index++;
HeaderAdVC *nextViewController;
if(self.index>arrayImages.count-1)
{
self.index=0;
[pageIndicator setCurrentPage:0];
nextViewController = [self viewControllerAtIndex:0];
}
else
{
nextViewController = [self viewControllerAtIndex:self.index];
}
[pageIndicator setCurrentPage:self.index];
[pageController setViewControllers:#[nextViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
}
and removing the timer in viewWillDisappear
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[_bannerTimer invalidate];
}
Problem :
My problem is when the loadNextController method is called my app stop responding.
If i switch to next page still getting the same problem on every view.
Do some changes like below , do all non-ui task in background thread and all UI operation in Main thread ,try this
- (void)loadNextController
{
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
self.index++;
HeaderAdVC *nextViewController;
if(self.index>arrayImages.count-1)
{
self.index=0;
[pageIndicator setCurrentPage:0];
nextViewController = [self viewControllerAtIndex:0];
}
else
{
nextViewController = [self viewControllerAtIndex:self.index];
}
dispatch_async(dispatch_get_main_queue(), ^{
[pageIndicator setCurrentPage:self.index];
[pageController setViewControllers:#[nextViewController]
direction:UIPageViewControllerNavigationDirectionForward
animated:YES
completion:nil];
});
});
}
i hope this will help you ..
Related
So basically I have two methods that I run when the user clicks an Annotation in the map.
- (void) methodA{
[UIView animateWithDuration:kRequestButtonAnimationDuration animations:^(void){
self.button.transform = CGAffineTransformMakeTranslation(0,-(self.navigationController.view.frame.size.height - self.button.frame.origin.y)); }]; }
- (void) methodB:(double)value andBoolean:(BOOL) boolean{
if (self.timer) {
[self.timer invalidate];
self.timer = nil;
}
if (boolean) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:value target:self selector:#selector(pullButtonUp) userInfo:nil repeats:NO];
} else{
self.timer = [NSTimer scheduledTimerWithTimeInterval:value target:self selector:#selector(showTabBar) userInfo:nil repeats:NO];
}}
-(void)pullButtonUp{
[(LLTabBarViewController*)self.tabBarController showTabBarAnimated];}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view{
[self methodA];
[self methodB:2.0 andBoolean:TRUE];
}
So during the first time I select an annotation, it works well: it runs methodA, then methodB after 2.0 seconds.
But when I try it again, it runs both A and B at the same time (basically methodA waits 2.0 seconds to execute).
Could this be related to Loops?
How should I track this problem? Any instrument? Which one?
I am a bit lost, help me please!
I think this is what you want to do
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
__weak typeof(self) weakSelf = self;
BOOL arbitraryBool = YES;
[UIView animateWithDuration:2
animations:^{
self.button.transform = CGAffineTransformMakeTranslation(0,-(self.navigationController.view.frame.size.height - self.button.frame.origin.y));
} completion:^(BOOL finished) {
if (finished) {
if (arbitraryBool) {
[weakSelf pullButtonUp];
} else {
[weakSelf showTabBar];
}
}
}]:
}
I'm using this following code to hide a UILabel after some seconds. Unfortunately if the user close the view during the NSInvocation is in progress the app crashes
- (void)showStatusBarwithText:(NSString*)text{
lblNotification.hidden=NO;
NSInvocation* invoc = [NSInvocation invocationWithMethodSignature:[lblNotification methodSignatureForSelector:#selector(setHidden:)]];
[invoc setTarget:lblNotification];
[invoc setSelector:#selector(setHidden:)];
lblNotification.text=text;
BOOL yes = YES;
[invoc setArgument:&yes atIndex:2];
[invoc performSelector:#selector(invoke) withObject:nil afterDelay:1];
}
and that's the error
*** -[UILabel setHidden:]: message sent to deallocated instance 0x1a8106d0
How can I solve? I have tried using
[NSObject cancelPreviousPerformRequestsWithTarget:lblNotification]
In the - (void)viewDidDisappear:(BOOL)animated but it doesn't work.
Here is how you should use performSelector
- (void)showStatusBarwithText:(NSString*)text{
lblNotification.hidden=NO;
[self performSelector:#selector(hideLabel) withObject:nil afterDelay:1];//1sec
}
-(void)hideLabel{
lblNotification.hidden= YES;
}
or with the timer
[NSTimer scheduledTimerWithTimeInterval:1//1sec
target:self
selector:#selector(hideLabel)
userInfo:nil
repeats:NO];
Why don't you just use dispatch_afer? The syntax is much more clear:
- (void)showStatusBarwithText:(NSString*)text{
lblNotification.hidden=NO;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
lblNotification.hidden = YES;
});
}
It's because you pass lblNotification instead of infoc object here:
[NSObject cancelPreviousPerformRequestsWithTarget:lblNotification]
It will be better to do this way:
- (void)showStatusBarwithText:(NSString*)text{
lblNotification.hidden=NO;
lblNotification.text=text;
[lblNotification performSelector:#selector(setHidden:) withObject:#(1) afterDelay:2];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated]
[NSObject cancelPreviousPerformRequestsWithTarget:lblNotification];
}
i am trying to using a Nstimer view transition on multiple view controllers but if i copy and paste it i get an error saying Duplicate declaration of method . how would i fix it ? please explain in your answer how to do this . i found out how to do this from this link .
http://x-code-tutorials.com/2013/06/19/nstimer-trigger-uiviewcontroller-transition/
- (void)viewDidAppear:(BOOL)animated {
[self startTimerMethod];
}
- (void) startTimerMethod {
transitionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(transitionView) userInfo:nil repeats:NO];
}
- (void) transitionView {
[self performSegueWithIdentifier:#"viewTransition" sender:self];
}
- (void)viewDidAppear:(BOOL)animated {
[self startTimerMethod];
}
- (void) startTimerMethod {
transitionTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(transitionView) userInfo:nil repeats:NO];
}
- (void) transitionView {
[self performSegueWithIdentifier:#"viewTransition" sender:self];
}
You have copy and paste below three methods two times let it define or declare single time:-
-(void)viewDidAppear:(BOOL)animated
-(void) startTimerMethod
-(void) transitionView
In my viewController I inserted a timer for a calculation of numbers taken directly from my database of Parse.com.
The timer is working correctly, were inserted in viewDidAppear and in ViewDidDisappear in such a way as to lock the sequence when changing view controller.
The problem I have is that when I change the view controller with the Push the timer does not stop you give an example:
I open the application and the calculation is done correctly with the animation of NSTimer.
Change View, and then I go back with the back button to view where the timer at this point I see that the numbers contiunano to increase every time I change view and go back ...
Can you explain where I'm wrong?
-(void)viewDidAppear:(BOOL)animated {
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
[self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]];
self.title = NSLocalizedString(#"", nil);
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self QueryForViewPrincipal];
[self QueryForCollectionView];
[self ShowBadgeNumber];
[self Timer];
[collectionView reloadData];
}
-(void)Timer{
timer = [NSTimer scheduledTimerWithTimeInterval:0.012 target:self selector:#selector(CalcoloMediadiLaurea) userInfo:nil repeats:YES];
}
-(void) CalcoloMediadiLaurea{
PFUser *CurrentUser = [PFUser currentUser];
NSNumber *NumeroUndici = [NSNumber numberWithInt:11];
NSNumber *NumeroTre = [NSNumber numberWithInt:3];
NSNumber *ValoreMediaPonderata = [CurrentUser objectForKey:FF_USER_MEDIA_PONDERATA];
int FFValoreTre = [NumeroTre intValue];
int FFValoreUndici = [NumeroUndici intValue];
double MediaPonderata = [ValoreMediaPonderata doubleValue];
double RisultatoMoltiplicazioneValoriPonderataUndici;
RisultatoMoltiplicazioneValoriPonderataUndici = MediaPonderata * FFValoreUndici;
double RisultatoMediaLaurea;
RisultatoMediaLaurea = RisultatoMoltiplicazioneValoriPonderataUndici / FFValoreTre;
CalcoloMediaLaureaLabel.text = [NSString stringWithFormat:#"%.1f", FFTickValoreMediaLaurea ];
FFTickValoreMediaLaurea++;
if(FFTickValoreMediaLaurea > RisultatoMediaLaurea){
[timer invalidate];
timer = nil;
}
}
-(void)viewDidDisappear:(BOOL)animated {
[self animatelayertopoint:0];
[self AnimationMenuView:600];
[self CalcoloMediadiLaurea];
}
The timer get rescheduled again on view did appear without getting invalidated to the previous one.You should make instance of timer in .h and then hold the reference of timer in it .And on view did appear when you are scheduling the timer just invalidate it and then schedule it again.
if([self.timer isValid])
{
[self.timer invalidate];
self.timer=nil;
self.timer=[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(CalcoloMediadiLaurea:) userInfo:nil repeats:YES];
}
This worked for me which is along the lines of the above answer but a little more explicitly stated.
- (void)viewWillAppear:(BOOL)animated
{
NSTimeInterval secondsBetween = [endDate timeIntervalSinceDate:currentTime];
secondsLeft = secondsBetween;
[self countdownTimer];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self.timer invalidate];
self.timer = nil;
}
//Initiates timer
- (void)countdownTimer
{
[self.timer invalidate];
self.timer = nil;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
It's because you are creating new timers without invalidating old ones. The timers don't get invalidated automatically, you have to do it yourself. So if U go on second view and return before your invalidate condition is true you will create new timer and have two of them :)... And so on.
I have a simple explosion animation that works just fine in any method in my class. However I want to call it once the timer runs out, from the timer update method. The problem is it will not work from here for whatever reason (something to do with the timer surely). It simply unhides my image.. no animation. I cannot figure out how to get it to work.
- (void)explosionAnimation
{
imgExplosion.hidden=FALSE;
//set starting point of explosion
CGRect explosionFrame = self.imgExplosion.frame;
explosionFrame.origin.x = explosionFrame.origin.y = -960.0f;
explosionFrame.size.width = explosionFrame.size.height = 1920.0f;
[UIView animateWithDuration:1.5f animations:^{
self.imgExplosion.frame = explosionFrame;
} completion:^(BOOL finished) {
self.imgExplosion.hidden = YES;
}];
}
-(void) createTimer
{
// Create timer instance
if (timer != nil){
[timer invalidate];
hasTimerStarted = NO;
}
// Initialize the timer.
timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerUpdater)
userInfo:nil repeats:YES];
}
- (void)timerUpdater{
if(!hasTimerStarted){
intTotalSeconds = [strTotalNumberofSeconds intValue];
hasTimerStarted = YES;
}
else{
intTotalSeconds--;
self.lblTimer.text = [self revertTimeToString:intTotalSeconds];
}
// if totalSeconds hits zero, then time is up! You lose!
if (intTotalSeconds == 0){
[timer invalidate];
[self explosionAnimation];
hasTimerStarted = NO;
[self addPlayAgainButton];
}
}
Try putting some delay or call explosion method on Main Thread like
[self performSelector:#Selector(explosionAnimation) withObject:nil afterDelay:1.0];