I am developing an app where the menu move away to reveal a second menu. I am moving the image with a NSTimer, and want it to stop when the image hits a certain coordinate on the screen. But what I am currently using is not working, it is moving the image, but it doesn't stop. What am I doing wrong? EDIT: This is Xcode 5
- (IBAction)showSubMenu:(id)sender {
moveTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(moveMenus) userInfo:nil repeats:YES];
[self stopMovement];
}
-(void)stopMovement {
if (mainMenu.center.y < -160) {
[moveTimer invalidate];
moveTimer = nil;
}
}
-(void)moveMenus {
mainMenu.center = (CGPointMake(mainMenu.center.x, mainMenu.center.y-1));
goButton.center = (CGPointMake(goButton.center.x, goButton.center.y-1));
Info.center = (CGPointMake(Info.center.x, Info.center.y-1));
helpButton.center = (CGPointMake(helpButton.center.x, helpButton.center.y-1));
subMenu.center = (CGPointMake(subMenu.center.x, subMenu.center.y-1));
description.center = (CGPointMake(description.center.x, description.center.y-1));
playEndless.center = (CGPointMake(playEndless.center.x, playEndless.center.y-1));
playQuick.center = (CGPointMake(playQuick.center.x, playQuick.center.y-1));
playSoundboard.center = (CGPointMake(playSoundboard.center.x, playSoundboard.center.y-1));
confirm.center = (CGPointMake(confirm.center.x, confirm.center.y-1));
}
Thanks for the help in advance!
Rafee
You need to call stopMovement every time your view move, so change your code like this :
- (IBAction)showSubMenu:(id)sender
{
moveTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:#selector(moveMenus) userInfo:nil repeats:YES];
}
- (void)stopMovement
{
if (mainMenu.center.y < -160)
{
[moveTimer invalidate];
moveTimer = nil;
}
}
- (void)moveMenus
{
mainMenu.center = (CGPointMake(mainMenu.center.x, mainMenu.center.y-1));
goButton.center = (CGPointMake(goButton.center.x, goButton.center.y-1));
Info.center = (CGPointMake(Info.center.x, Info.center.y-1));
helpButton.center = (CGPointMake(helpButton.center.x, helpButton.center.y-1));
subMenu.center = (CGPointMake(subMenu.center.x, subMenu.center.y-1));
description.center = (CGPointMake(description.center.x, description.center.y-1));
playEndless.center = (CGPointMake(playEndless.center.x, playEndless.center.y-1));
playQuick.center = (CGPointMake(playQuick.center.x, playQuick.center.y-1));
playSoundboard.center = (CGPointMake(playSoundboard.center.x, playSoundboard.center.y-1));
confirm.center = (CGPointMake(confirm.center.x, confirm.center.y-1));
// Call here
[self stopMovement];
}
Related
I couldn't attach a photo of the touch bar. But if you have enabled the touch bar, when you click on the [Day Week Month Year] segments in the Calendar app, you can see the different type of date pickers in the touch bar. I have to create a same date picker. Any help is much appreciated.
The scrolling months might be a single NSScrubber.
There are some text-based and image-based examples of this in Apple's NSTouchBar Catalog source. Have a look at the ScrubberViewController.m file in that project.
Below is some simplified code for setting up a single NSScrubber to display the months. You'd probably want to properly localize month names, and add code to highlight the current choice.
static NSString *kMyScrubberID = #"com.mycompany.myapp.month.scrubber";
self.myTitlesArray = [NSArray arrayWithObjects:
#"Jan",
#"Feb",
#"Mar",
#"Apr",
#"May",
#"Jun",
#"Jul",
#"Aug",
#"Sep",
#"Oct",
#"Nov",
#"Dec",
nil];
// NSTouchBarDelegate
- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar makeItemForIdentifier:(NSTouchBarItemIdentifier)anIDstr {
if ([anIDstr isEqualToString:kMyScrubberID]) {
NSCustomTouchBarItem *theScrubberItem = [[NSCustomTouchBarItem alloc] initWithIdentifier:anIDstr];
NSScrubber *theScrubber = [[NSScrubber alloc] initWithFrame:NSMakeRect(0, 0, 300, 30)];
theScrubber.scrubberLayout = [[NSScrubberFlowLayout alloc] init];
[theScrubber registerClass:[NSScrubberTextItemView class] forItemIdentifier:anIDstr];
theScrubber.delegate = (id<NSScrubberDelegate>)self;
theScrubber.dataSource = (id<NSScrubberDataSource>)self;
theScrubber.mode = NSScrubberModeFree;
theScrubber.continuous = YES;
theScrubber.floatsSelectionViews = YES;
theScrubber.showsArrowButtons = NO;
theScrubber.selectionOverlayStyle = nil;
theScrubber.selectionBackgroundStyle = [NSScrubberSelectionStyle roundedBackgroundStyle];
theScrubber.backgroundColor = [NSColor colorWithRed:51.0/255.0 green:51.0/255.0 blue:51.0/255.0 alpha:1.0];
theScrubberItem.view = theScrubber;
return theScrubberItem;
} else {
return nil;
}
}
// NSScrubberDelegate
- (void)scrubber:(NSScrubber *)scrubber didSelectItemAtIndex:(NSInteger)selectedIndex {
NSLog(#"selected month = '%#'", [self.myTitlesArray objectAtIndex[selectedIndex]);
}
// NSScrubberDataSource
- (NSInteger)numberOfItemsForScrubber:(NSScrubber *)scrubber {
return [self.myTitlesArray count];
}
- (NSScrubberItemView *)scrubber:(NSScrubber *)scrubber viewForItemAtIndex:(NSInteger)index {
NSScrubberTextItemView *theItemView = [scrubber makeItemWithIdentifier:kMyScrubberID owner:nil];
if (index < [self.myTitlesArray count]) {
theItemView.textField.stringValue = [self.myTitlesArray objectAtIndex:index];
}
return theItemView;
}
// NSScrubberFlowLayoutDelegate
- (NSSize)scrubber:(NSScrubber *)scrubber layout:(NSScrubberFlowLayout *)layout sizeForItemAtIndex:(NSInteger)itemIndex {
return NSMakeSize(60, 30);
}
I'm trying to make an NSButton (but I could use the technique for iOS too, so any answers are welcome).
I have a button where hiding/enabling is turned on and off:
-(void)textDidChange:(NSNotification *)notification
{
timerStatus = 0;
timerTest = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(changeButtonState:)
userInfo:nil
repeats:YES];
}
-(void) changeButtonState:(id) sender {
NSLog(#"%s", __FUNCTION__);
if (timerStatus == 2) return;
if (timerStatus == 0) {
timerStatus = 1;
saveButton.enabled = YES;
saveButton.hidden = NO;
} else {
timerStatus = 0;
saveButton.enabled = NO;
saveButton.hidden = YES;
}
}
The button blinks ok, but after it's associated method is fired (in this case a save action), I want the timer to stop and the button to stop blinking. It's this last part that's giving me a headache.. Any help appreciated.
- (IBAction)saveItemNotes:(id)sender
{
NSLog(#"%s", __FUNCTION__);
<do my save stuff here>
timerStatus = 2;
[timerTest invalidate];
timerTest = nil;
}
Just invalidate your timer in that same method where you change the button state.
Better yet, don't do it this way.
Use Core Animation instead if you want to draw attention to an interface item.
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];
I'm creating a memory game and want to change the images of four buttons each iteration in a for-loop. What actually happens is that nothing happens until the last iteration of the loop.
When the button is pressed:
- (IBAction)bNewRound:(id)sender {
for (int i = 0; i < 10; i++) {
numbers1[i] = arc4random()%4+1;
NSLog(#"%i: %i", i, numbers1[i]);
if (numbers1[i] == 1) {
[self b1On];
}
if (numbers1[i] == 2) {
[self b2On];
}
if (numbers1[i] == 3) {
[self b3On];
}
if (numbers1[i] == 4) {
[self b4On];
}
sleep(1);
}
}
The method for changing the images of the buttons:
- (void)b1On {
NSLog(#"b1 state1");
[self.button1 setBackgroundImage:[UIImage imageNamed:#"memory_green.png"] forState: UIControlStateNormal];
bool1 = FALSE;
[self b2Off];
[self b3Off];
[self b4Off];
}
- (void)b1Off {
// NSLog(#"b1 state2");
[self.button1 setBackgroundImage:[UIImage imageNamed:#"memory_grey.png"] forState: UIControlStateNormal];
bool1 = TRUE;
}
(only for button 1 but you get it)
I follow the code in the log and everything works fine, every second a new number is generated and saved in the array, the b1On-method (or b2On, b3On etc) runs but the line
[self.button1 setBackgroundImage:[UIImage imageNamed:#"memory_green.png"] forState: UIControlStateNormal];
wont change the image each iteration.
But when the for-loop is over the last (random) button in the array will change color to green.
Why arenĀ“t the images updated for every iteration of the for-loop?
Thanks
Never ever use sleep() on the main thread
UI updates don't happen immediately. They happen at the end of the current run loop, that means after your method is done.
You could use a NSTimer. Something like this should work:
- (void)timerFired:(NSTimer *)timer {
_timerCount--;
if (_timerCount <= 0) {
[timer invalidate];
}
// do something
}
- (void)startTimer {
[_timer invalidate];
_timerCount = 10;
_timer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
In my app project I want to be able to tap a button, wait 5 seconds, and then a UILabel and UIImageView appear. Here's what I have so far:
- (IBAction)startTimer
{
responseBox.placeholder = #"Message Here";
timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(timerStop) userInfo:nil repeats:YES];
mainInt +=1;
}
- (void)timerStop
{
if (mainInt == 5)
{
[timer invalidate];
titleLabel.hidden = NO;
messageLabel.hidden = NO;
messageLabel.text = #"Message";
image.hidden = NO;
}
}
Everything's linked correctly, what's going on?
mainInt is only incremented when you press the startTimer button, so that does you no good in timerStop. Also, if you want to increment mainInt correctly, use mainInt++;
Try this:
- (IBAction)startTimer
{
responseBox.placeholder = #"Message Here";
timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(timerStop) userInfo:nil repeats:YES];
mainInt++;
}
- (void)timerStop
{
[timer invalidate];
titleLabel.hidden = NO;
messageLabel.hidden = NO;
messageLabel.text = #"Message";
image.hidden = NO;
}