NSTimer no effect...? - cocoa

I tried to call [self setNeedsDisplay:YES] in a NSTimer selector in order to trigger the drawRect method.
At first, I put the NSTimer init code in a button func:
-(IBAction)buttonPush:(id)sender
{
myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(myTimerAction:)
userInfo:nil
repeats:YES];
}
-(void)myTimerAction:(NSTimer *) timer
{
[self setNeedsDisplay:YES];
}
The "setNeedsDisplay" is called normally but the code inside the drawRect is never called:
- (void)drawRect:(NSRect)dirtyRect
{
NSLog(#"drawRect");
}
Then I tried to move the NSTimer init code to "- (id)initWithFrame:(NSRect)frame", then everything works just fine.
(the drawRect is called correctly every 1 sec).
What's the difference between the two methods above?
What should I do if I want to trigger the Timer in a button?

Just wondering, in what class does that code reside? I would assume the buttonPush: action is inside a controller, correct?
If so, then you should have:
-(void)myTimerAction:(NSTimer *) timer
{
[[self view] setNeedsDisplay:YES];
}
because setNeedsDisplay: is a method of NSView, not NSViewController.
(BTW probably the reason why it works if you put it inside initWithFrame: is because that one is a NSView initializer: I'm guessing that when you move the code there you are also moving the myTimerAction: method, which then has "self" referring correctly to the view.)

Since it works when you use initWithFrame:, the problem is probably that buttonPush: isn't hooked up correctly. Try setting a breakpoint in buttonPush: an see if it is actually called when you click the button.

Related

how do i reference the window associated with a nswindowcontroller

I have a subclassof NSWindowController with an associated xib file.
From my app delegate I display this using the following code:
if(!wc)
wc = [[NSWindowController alloc]initWithWindowNibName:#"MyNewWindowController"];
[wc showWindow:nil];
This displays the window. Now I want to reference that window in the new window controller but can't work out how. Specifically I have a button on the new window and I want to write something like:
- (IBAction)doStuffAndCloseWindow:(id)sender
{
[self doSomeStuff];
[*window* orderOut:nil];
}
I've tried creating a window variable (like the one created in appdelegate) but the compiler says my window variable is private.
So have do I declare and reference a window in my MyNewWindowController.m?
Thanks
That would be the 'window' method of NSWindowController. It's also a property that you can access via ".window".
So, in the first code snippet, that would be:
[wc window]
and in the second code snippet (assuming "doStuffAndCloseWindow" is part of your subclassed NSWindowController):
- (IBAction)doStuffAndCloseWindow:(id)sender
{
[self doSomeStuff];
[[self window] orderOut:nil];
}
Thanks to Michael, see above, first declare your subclassed NSwindowController thus
#property IBOutlet MyNewWindowController *wc;
Then in the implementation of the subclassed window controller, you can refer to the associated window with
[[self window] .....];
For example
[[self window] orderOut:self];

how to add a uibuttonitem by calling a method from another class

Due to the neeeds of the aplication I need to call a method from a cell class of a collection view. The method is in a detail view controller which implementes the collection view .
If I call the method completely from viewDidLoad of the detail view controller at aplication start everything goes well and the button is added in the navigation bar as intended, but when I call the same method from the cell class nothing happens. Do I forget something?
Here is the code
collectionViewCell.m
- (void) addButtonToNavigationBar {
DetailViewController *dvc = [[DetailViewController alloc]init]
[dvc implementButton];
}
DetailViewController.h
- (void) implementButton;
DetailViewController.m
- (void) implementButton {
addButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(editTable)];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleBordered];
[self.navigationItem setRightBarButtonItem:addButton animated:YES];
Thank you for any hint.
When you write DetailViewController *dvc = [[DetailViewController alloc]init]; you are creating a new controller. It's not the one that already exists.
For your situation, you might consider having the controller listen for a NSNotification from the cell and call implementButton when it receives it.

The blue focus ring outside NSTextField missing?

In normal case, a blue retangle would appear outside a NSTextField object which becomes the first responder, like this image:
link for Normal Case
However, I got a NSTextField that have no the blue border outside. Why is that?
Here is how it happerns:
1> I create a typical MAC OS app.
2> I switch app's subview by calling the corresponding view's addSubview: and removeFromSuperview methods.
3> In one subview (which is actually the image referenced above) I click the "Next" button. Its action is something like this (defined in the subview's controller .m file):
- (IBAction)actionNextClicked:(id)sender{
//_hdlThreadNext is a NSThread object
[[_hdlThreadNext alloc] initWithTarget:self selector#selector(threadNext:) object:nil];
[_hdlThreadNext start];
}
And the thread is like:
- (void)threadNext:(id)sender{
#autoreleasepool{
BOOL success;
[CATransation begin];
/* send username and password and decrypt responce */
... // balabala... and set "success"
if (success){
[[self view] removeFromSuperview];
[self sendMessageToSuperview:#"Add Next View"]; // Superview's method, telling superview to call addSubview: to add another subview
}
else{
/* Nothing special to do */
}
[CATransation commit];
}
}
4> The subview switch to another one. Its combo view seemed to be OK: image for combo view
But the other NSTextView's blue border would NOT appear anymore!
Does Any guy know what wrong I had done? Thank you very much!
Perhaps I did totally wrong programming, so that few people met this problem.
I found a way to solve this problem. I mentioned that all (or most of?) the graphic changes should be done in main thread in a blog. Therefore I change the "if(success)" as:
if(success){
dispatch_async(dispatch_get_main_queue()' ^{
[[self view] removeFromSuperview];
[self sendMessageToSuperview:#"Add Next View"];
});
}
Solved, the focus rings come back.

why does selecting a tabbarController index programatically doesnt call delegate method

when we touch the tabbaritem of the tabbarcontroller the delegate methods are called:
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
but when try to do the same thing programmatically, i.e.
[self.tabbarController setSelectedIndex:selectedIndexNo];
or
[self.tabBarController setSelectedViewController:[self.tabBarController.viewControllers objectAtIndex:0]];
the delegate methods are not called. What is the reason for that?
override UITabBarController setSelectedIndex:
-(void)setSelectedIndex:(NSUInteger)selectedIndex
{
//must call super function.
[super setSelectedIndex:selectedIndex];
[self myMethod];
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
[self myMethod];
}
When you are setting them yourself via code, than you are aware that this is the time when the delegate method will be called. so whatever you wish to do you can do it at the time of setting the index programmatically. Say you want to call a method aMethod on tabbardelegate being called. you can call the method as soon as you set the index.
[self.tabbarController setSelectedIndex:selectedIndexNo];
[self aMethod];

linking a NSTimer to a NSProgressIndicator

I need to make an NSTimer that will tell another class to fire in 10 seconds, and I would also like to use it to animate a determinate NSProgressIndicator. I also need to know how to change my indeterminate progress indicator to determinate. I was able to find a Apple doc on this, however a more in-depth explanation would help.
From indeterminate to determinate NSProgressIndicator You can change in IB. Select Your progressIndicator and go to Attributes inspector and uncheck Indeterminate checkbox like this:
Or it can be done programatically:
[progressIndicatorOutlet setIndeterminate:NO];
Note: progressIndicatorOutlet is Your NSProgressIndicator outlet, so don't forget to IBOutlet it.
Determinate NSProgressIndicator animation:
It's very simple just set and change value like this:
[progressIndicatorOutlet setDoubleValue:10];
Note: progressIndicatorOutlet is Your NSProgressIndicator outlet, so don't forget to IBOutlet it.
NSTimer:
Simple timer example:
//Place this where You want to call class after 10 sec. (for example: when button pressed)
//It will call class with name callAfter10sec after 10 sec. Place in there what You need to do.
[NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(callAfter10sec:)
userInfo:nil
repeats:YES];
Don't forget to add class which I mentioned in comments like this:
-(void)callAfter10sec:(NSTimer *)time {
// Do what You want here
}
Hope it helps.
Using the following way we can achieve what is expected
NSInteger progressValue;
NSTimer *timerObject;
progressValue = progressMaxValue;
timerObject = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(incrementProgressBar) userInfo:nil repeats:YES];
[timerObject fire];
[self.progressBar setMinValue:progressMinValue];
[self.progressBar setMaxValue:progressMaxValue];
[self.progressBar setDoubleValue:progressValue];
- (void)incrementProgressBar {
// Increment the progress bar value by 1
[self.progressBar incrementBy:1.0];
progressValue--;
[self.progressBar setDoubleValue:progressValue];
}

Resources