I developed an iOS app that has two UIButton however the buttons seem to be lagging sometimes when I press them. Sometimes the lag is really bad (takes 10 seconds sometimes). I am almost positive it has something to do with the NSTimer I am using. I just want to make it so the UIViewControllers are switched as soon as the buttons are pressed, I don't want there to be any delay at all. Here is my code:
RealTimeModeViewController.m
#import "RealTimeModeViewController.h"
#interface RealTimeModeViewController ()
#end
#implementation RealTimeModeViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(UpdateTime:)
userInfo:nil
repeats:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)UpdateTime:(id)sender
{
// This is where I do everything in my app
}
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(UpdateTime:)
userInfo:nil
repeats:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)UpdateTime:(id)sender
{
// Most of code goes here
}
#end
The two UIButton are connected to each other ViewController via Modal style. Maybe I am supposed to put the buttons in the main thread? I am not very familiar with threads. Thank you.
If I had to guess, you are doing something in the UpdateTime: method that is time consuming. Because it is on the main thread and it is running every 1 second, you are probably slowing down everything else. UIButton events are on the main thread, so it's likely that because you are doing everything on the main thread, it is "clogged".
For a timer implementation that won't be as accurate, but will not hang the main thread, see this answer: https://stackoverflow.com/a/8304825/3708242
If you must have the consistency of the NSTimer implementation, try reducing the amount of stuff that UpdateTime: does.
I've had this problem before. You should use UIActivityIndicatorView
The button delay is probably caused by the UpdateTime method. Use UIActivityIndicatorView in ViewWillAppear of ViewDidLoad then perform the UpdateTime method.
Here is what I mean:
-(void) ViewDidLoad
{
UIActivityIndicatorView *act = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[act setFrame:CGRectMake(320/2-50, 130, 100, 100)];
act.layer.cornerRadius = 10;
[act.layer setBackgroundColor:[[UIColor colorWithWhite: 0.0 alpha:0.30] CGColor]];
UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, act.frame.size.width, 20)];
[lable setText:[NSString stringWithFormat:#"%#", string]];
[lable setFont:[UIFont fontWithName:#"Helvetica-Light" size:12.0f]];
[lable setTextAlignment:NSTextAlignmentCenter];
[lable setTextColor:[UIColor whiteColor]];
[act addSubview:lable];
[self.view addSubview: act];
[act startAnimating];
// perform the method here, and set your delay time..
[self performSelector:#selector(UpdateTime:) withObject:nil afterDelay:1.0];
}
Then...
- (void)UpdateTime:(id)sender
{
// Most of your code
}
Comment and tell me if this helps :)
Related
I'm a beginner to Xcode nd Objective-C! I'm making an ios app which is basically a stop watch. The idea is only to have two buttons. One to reset the stopwatch and the other to start and stop the clock. (Basically, you click the start button which then turns into a stop button which when clicked will stop the stopwatch. The problem is I have two errors which are the same and read the following: (I don't know how to fix them which is the question!)
No visible #interface fro 'UIButton' declares the selector 'setTitle:forControlState:'
This has come up twice at two points! Point one:
[button setTitle:#"Start" forControlState:UIControlStateNormal];
And point two...
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
Here is my code for VeiwController.h:
//
#import <UIKit/UIKit.h>
float addingtheTime;
#interface ViewController : UIViewController
{
IBOutlet UILabel *Label;
NSTimer *Timer;
}
#end
Here is my code for ViewController.m
//
#import "ViewController.h"
#interface ViewController ()\
#end
#implementation ViewController
-(IBAction)Start:(id)start
{
UIButton *button = (UIButton *)start;
if (button.tag == 0){
button.tag = 1;
[button setTitle:#"Start" forControlState:UIControlStateNormal];
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(addingthetime) userInfo:nil repeats:YES];
}else {
button.tag = 0;
[button setTitle:#"Stop" forControlState:UIControlStateNormal];
//Invoke your method to stop Timer.
}
}
-(IBAction)Restart:(id)sender
{
[Timer invalidate];
addingtheTime = 0;
Label.text = [NSString stringWithFormat:#"0.00"];
}
-(void)addingthetime
{
addingtheTime = addingtheTime + 0.01;
Label.text = [NSString stringWithFormat:#"%.2f", addingtheTime];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Please note I am a beginner so please explain as much as you can and thanks you in advance for any help!!!
its forstate not forControlState
[button setTitle:#"start" forState:UIControlStateNormal];
[button setTitle:#"stop" forState:UIControlStateNormal];
In my project there is huge number of UIlabels. I have created one separate custom class for UILabel and I have set all label's properties in that class.
Here my main requirement is some labels' color is white and some labels' text color is black but color is not applying.
CustomUILabel class:-
#import "CustomLabel.h"
#implementation CustomLabel
-(void)layoutSubviews{
[self setupUI];
}
- (void)setupUI {
[self setTextAlignment:NSTextAlignmentLeft];
[self setFont:[UIFont fontWithName:#"Futura" size:14.0]];
[self setBackgroundColor:[UIColor clearColor]];
[self setTextColor:[UIColor blackColor]];
}
#end
Main class:-
#import "MainViewController.h"
#interface MainViewController (){
}
#end
#implementation MainViewController
#synthesize label1,label2;
- (void)viewDidLoad {
[super viewDidLoad];
label1.textColor = [UIColor whiteColor];
label2.textColor = [UIColor blackColor];
}
When you override layoutSubviews, you must call [super layoutSubviews]. But that's not your problem here. The problem is that you're calling setupUI in layoutSubviews, and you shouldn't. Layout happens after viewDidLoad, so your attempt to set the color in viewDidLoad gets overridden later during layout, when setupUI runs.
You should be calling setupUI from the init methods of your subclass:
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupUI];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setupUI];
}
return self;
}
And you shouldn't override layoutSubviews at all in CustomLabel.
The problem is with your layoutSubview method and your setupUI method.
layoutSubviews is not the proper place to call setupUI. layoutSubviews can be called many times and is most likely being called a couple of times after viewDidLoad is called which is why the colors are being reset back to black.
And always call [super layoutSubviews]; in your layoutSubviews method.
The better place to call your setupUI method is from one or more of the appropriate init... methods and possibly awakeFromNib.
I have two NSTimer. The problem is that my countdown timer messes up my background positioning as soon as the countdown timer stops. The background moves properly up until the point where the background timer stops. Then it will automatically reposition the background to the starting position, which I do not want because it seems glitchy when it happens. I want it to keep flowing smoothly as soon as the countdown timer stops. If I were to take the countdown timer out, the background movement works perfectly. Here is my code:
PlayViewController.h
#import <UIKit/UIKit.h>
#interface PlayViewController : UIViewController
{
int countdownStatus;
IBOutlet UIImageView *background;
NSTimer *backgroundMovement;
NSTimer *gameCountdownTimer;
}
#property (strong, nonatomic) IBOutlet UILabel *countdownLabel;
- (void)backgroundMoving;
- (void)gameCountdown;
#end
PlayViewController.m
#import "PlayViewController.h"
#interface PlayViewController ()
#end
#implementation PlayViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.countdownLabel.text = #"3";
countdownStatus = 2;
gameCountdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(gameCountdown) userInfo:nil repeats:YES];
backgroundMovement = [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:#selector(backgroundMoving) userInfo:nil repeats:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)backgroundMoving
{
background.center = CGPointMake(background.center.x - 1, background.center.y);
CGRect backgroundFrame = background.frame;
if(backgroundFrame.origin.x < -370)
{
CGRect myFrame = background.frame;
myFrame.origin.x = 0;
myFrame.origin.y = 0;
background.frame = myFrame;
}
}
- (void)gameCountdown
{
if(countdownStatus == 2)
self.countdownLabel.text = #"2";
else if(countdownStatus == 1)
self.countdownLabel.text = #"1";
else
self.countdownLabel.text = #"";
countdownStatus--;
}
#end
Moving text like marquee style from bottom to top in iOS application. i have tried this long time using google search but i could not get perfect answer for this question please provide any code for this question. i an new to iOS application.
Try this
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
NSTimer *timer;
UILabel *label ;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
timer =[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(scrollText:) userInfo:nil repeats:YES];
label = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 250, 20)];
label.text =#"This is a string to be scroll";
[self.view addSubview:label];
}
-(void)scrollText:(id)parameter{
if (label.frame.origin.y <= 50) {
[label setFrame:CGRectMake(label.frame.origin.x, 400, label.frame.size.width, label.frame.size.height)];
}
else
[label setFrame:CGRectMake(label.frame.origin.x, label.frame.origin.y-5, label.frame.size.width, label.frame.size.height)];
}
#end
You can find the same implementation in the below link. It's really awesome place for COCOA CONTROL.
COCOA CONTROLS
Check this answer.
.h
NSTimer *timer;
float timeDuration;
.m
-(void)viewDidLoad {
[super viewDidLoad];
timeDuration=1.0f;
timer = [NSTimer scheduledTimerWithTimeInterval:timeDuration target:self selector:#selector(marqueeAnimation) userInfo:nil repeats:YES];
}
-(void)marqueeAnimation{
UIImageView *imgView=[[UIImageView alloc]initWithFrame:CGRectMake(100, -100, 100, 100)];
[imgView setImage:[UIImage imageNamed:#"root.PNG"]];
[self.view addSubview:imgView];
NSString *keyPath = #"transform.translation.y";
CAKeyframeAnimation *translation = [CAKeyframeAnimation animationWithKeyPath:keyPath];
translation.duration = timeDuration;
translation.autoreverses = NO;
NSMutableArray *values = [[NSMutableArray alloc] init];
[values addObject:[NSNumber numberWithFloat:0.0f]];
CGFloat height = [[UIScreen mainScreen] applicationFrame].size.height;
[values addObject:[NSNumber numberWithFloat:height]];
translation.values = values;
NSMutableArray *timingFunctions = [[NSMutableArray alloc] init];
[timingFunctions addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
translation.timingFunctions = timingFunctions;
[imgView.layer addAnimation:translation forKey:keyPath];
}
Try this. This works. Try this in a sample app and then include it in your app.
#import "ViewController.h"
#interface ViewController ()
#property(nonatomic, retain) NSTimer *timer;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[_txtView setText:#"hi..."];
_timer = [NSTimer scheduledTimerWithTimeInterval:0.01f target:self selector:#selector(marqueeScroll) userInfo:nil repeats:YES];
}
-(void) marqueeScroll
{
[_txtView setFrame:CGRectMake(_txtView.frame.origin.x, _txtView.frame.origin.y-1.0, _txtView.frame.size.width, _txtView.frame.size.height)];
CGRect screen = [[UIScreen mainScreen] bounds];
if(_txtView.frame.origin.y <= 0 )
{
[_txtView setFrame:CGRectMake(_txtView.frame.origin.x, screen.size.height,_txtView.frame.size.width, _txtView.frame.size.height)] ;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Let me know if there are any errors.
I want to stop ActivityIndicator after some time. I guess this can be achieved if I call a method after some time which stops activity indicator.
It can be achieved using NSTimer, but I don't know how. An example with code snippet will be great.
In .h class,
UIActivityIndicatorView *activity;
And used this code to your implementation class,
- (void)viewDidLoad {
[super viewDidLoad];
//initialise activityIndicator and add it to view
activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activity.frame = CGRectMake(150,200, 20, 20);
[self.view addSubview:activity];
[activity startAnimating];
//call timer to fire after your required time
[NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:#selector(timerMethod:) userInfo:nil repeats:NO];
}
Timer Action,
-(void) timerMethod : (NSTimer *) theTimer {
// after 1.5 seconds, the activity indicator will be hidden.
[activity stopAnimating];
}