Execute something on application startup? - objective-c

I have a class in my application which handles all the controls and all the functions and variables are stored in it. How can I add a function which handles the application startup to it?
So basically I need to handle 'applicationDidFinishLaunching' in my class as well as in the application delegate.
How do I do that?

NSApplication sends the NSApplicationDidFinishLaunchingNotification notification, so you should just be able to register for that in your class:
- (void)awakeFromNib
{
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:#selector(appDidLaunch:)
name:NSApplicationDidFinishLaunchingNotification
object:nil];
}
- (void)appDidLaunch:(NSNotification*)notification
{
NSLog(#"Blast off!");
}
There's a general pattern here, in that Cocoa classes that have delegate methods with a method signature that passes a single notification parameter, such as the ‑(void)applicationDidFinishLaunching:(NSNotification*)notification delegate method of NSApplication, will also post a notification when the delegate method is called.
For example, NSWindow has a lot of delegate methods with this kind of signature, such as:
- (void)windowDidResize:(NSNotification *)notification
If you look at the docs for this method, you'll see that the notification that is passed to this delegate method is a NSWindowDidResizeNotification. You can then find more detail about this notification in the notifications section of the NSWindow docs.
This type of delegate method is often used when there is a likelihood that more than one object will be interested in the delegate information.

Related

NSNotificationCenter addObserver in subclass

I register for being notified in superclass (UIViewController) like so:
SuperClass.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(notification:)
name:#"Notification"
object:nil];
}
- (void)notification:(NSNotification *)notification {
// Do something for SuperClass with the notification
}
Now In subclass (subclass of SuperClass.m) I also listen for the same notification like so:
SubClass.m
- (void)notification:(NSNotification *)notification {
// Do something specific for SubClass with the notification
}
Is this an acceptable (codewise) way to deal with having a general behaviour when acting on a notification in a superclass and to having a more specific behaviour when acting on a notification in a subclass?
Usually when you want to allow more specific behavior in the subclass, while still maintaining the general behavior in the superclass, you have the subclass call super. For example, the -[UIViewController viewDidAppear:] documentation says:
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
So your notification setup is fine (although it's a bit weird to have a NSNotification object as a parameter to a method you expect to be overridden) — but you'll want to call [super notification:notification] to get the superclass's behavior as well.

textDidChange not called ( NSTextFieldDelegate )

Step 1. Add a NSTextField in xib
Step 2. Add NSTextFieldDelegate in .h file,Control-drag NSTextField to File's Owner to set delegate to it
Step 3, In .m file add the method:
- (void)textDidChange:(NSNotification *)notification{
NSLog(#"textDidChange");
}
but the method textDidChange: not called?
Is any mistake?
The file's owner isn't the app delegate -- is the app delegate where you put that method? You should control drag to the blue cube labeled app delegate.
After Edit: The message that the delegate receives is controlTextDidChange: not textDidChange, so implement that one instead.
You need to register an observer to listen for the NSNotification.
// When the NSWindow is displayed, register the observer.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(controlTextDidChange:) name:NSControlTextDidChangeNotification object:nil];
- (void)controlTextDidChange:(NSNotification *)obj {
// You can get the NSTextField, which is calling the method, through the userInfo dictionary.
NSTextField *textField = [[obj userInfo] valueForKey:#"NSFieldEditor"];
}
It seems, the object returned by NSFieldEditor is a NSTextView, instead of the same NSTextField object, which you may expect.
However, according to Apples documentation, if you implement this method and the controls delegate is registered to this object, the notification shall be automatically registered.
The control posts a NSControlTextDidChangeNotification notification, and if the control’s delegate implements this method, it is automatically registered to receive the notification
Source: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSControl_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/controlTextDidChange:

Setting AVAudioPlayer Delegate to multiple classes?

Quick question: Is it possible to set the delegate of an AVAudioPlayer instance to more than one class?
In my program, I want two classes to be notified when a sound has been finished playing, but I am unsure of how to do that.
Any help would be appreciated.
Well it is something not possible. but you can do it by registering and notifying notification. Here is code for registering and notifying classes in objective c.
So you can set one class a delegate and there you can notify other classes
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
NSLog(#"delegate called");
[[NSNotificationCenter defaultCenter]
postNotificationName:AUDIO_PLAYER_FINISHED_PLAYING object:nil];
}
No, a delegate is always just one instance.
You could make a new class that is the delegate and make it send an NSNotification to notify the other two classes about the event.

Exchange data between un-related (table)viewcontrollers?

I have a app with TabBar, under the main tabbar there are navigation controllers, under these there are 'branches' of tableviewcontollers.
How can I make two unrelated, non segue-connected, under two different tab icons viewcontrollers exchange information between them?
Tried with delegating but I can't get the instance variable to the delegator from the delegatee (there's no relation between them, no segue.destinationviewcontroller etc)
any ideas?
practical:
the app shows list of subitems (the parent tableview has the items), andon the other tab the recent items that were selected are getting added (but maxiumum 10 and sorted by most recent).. been breaking my ** on it...
thanks
I find NSNotifications not the best way to do this since you do couple the unrelated TableViewControllers. I think the flow of information in an application is crucial.
The solution I would personally favor is having a central class, that manages the global data for your application. This can be the AppDelegate class or an arbitrary manager class that manages the flow of data and "pulls the strings" and mediates between the different independent ViewControllers.
Example:
Using this code you can get hold of your UITabBarController and set your class as the delegate of your ViewControllers etc.:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController *rootTabBarController = (UITabBarController *)self.window.rootViewController;
MyFirstTableViewController *firstVC = [rootTabBarController.viewControllers objectAtIndex:0];
firstVC.delegate = self; // Get informed about events in the first ViewController
MySecondTableViewController *secondVC = [rootTabBarController.viewControllers lastObject]; // Assuming you only have two Tabs
// Once you have the rootTabBarController you can cast it to the corresponding ViewController and access any nested UIViewControllers
return YES;
}
#pragma mark - MyFirstTableViewControllerDelegate
-(void)firstTableViewController:(MyFirstTableViewController *)sender didSomethingFancy:(MyFancyObject *)fancy{
// Do stuff like fetching some data, based on the event from the first ViewController
// Maybe tell the secondVC to refresh its data etc. etc.
}
Have you considered posting an NSNotification, passing the data you want to transfer in userInfo?
From the Apple documentation:
The object sending (or posting) the notification doesn’t have to know
what those observers are. Notification is thus a powerful mechanism
for attaining coordination and cohesion in a program. It reduces the
need for strong dependencies between objects in a program (such
dependencies would reduce the reusability of those objects).
The class sending a notification does it as follows:
[[NSNotificationCenter defaultCenter] postNotificationName: <notification-name>
object: self
userInfo: <your-user-info>];
and the class listening for the notification registers for notifications using:
[[NSNotificationCenter defaultCenter] addObserver: self
selector: #selector(someMethod:)
name: <notification-name>
object: nil];
and has a method:
- (void) someMethod: (NSNotification *) notification
{
NSDictionary * myInfo = notification.userInfo;
//do something with myInfo
}
You can use #property and #synthesize to create default getters and setters. You can aso create your own getters and setters manually.

Objective-C game development: communication between components

I am using Cocos2d game development framework for iPhone.
Let's focus on the battle scene:
The battle scene has as children: battlers layer, HUD layer, menu layer, background layer, etc...
Sometimes, it is necessary that my battlers layer "contacts" my HUD layer (like call a function within it).
I find this hard. Basically, my battlers layer needs some kind of.. instance or reference of the HUD layer in order to call a function within it, right? But I don't know how to have such thing.
Currently, this is what I do:
The battlers layer will run a function in the scene (its parent), and, inside such function, I will "locate" the HUD layer child, and call the function I need in it.
Now, that is kind of inconvenient. What would you do in such situation?
It sounds to me that you may have over-designed this. What I might do is something like this.
I'd have an IScene. Each of my scene classes implements this IScene. IScene has a property called "HUD", another called "Menu", etc.
The current IScene is set into a global static instance ::CurrentScene
When the current scene needs to contact the menu, I say: ::CurrentScene->Menu->SomeFuncion().
Would that work for you?
I'd suggest you take a look at Cocoa's NSNotificationCenter and related classes. Apple has a guide to the subject here.
It might work something like this.
In your HUD layer, you subscribe to notifications with the name #"battleLayerStuff":
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(doThisWhenSomethingHappens:)
name:#"battleLayerStuff"
object:nil];
And in your battle layer, when something happens, you post a notification with the same name:
[[NSNotificationCenter defaultCenter] postNotificationName:#"battleLayerStuff"
object:battleObject];
The object part is optional, but can be helpful if you want to send more information than just "something happened".
If you want to extract information from the object you send you do this in the doThisWhenSomethingHappens: method:
- (void)doThisWhenSomethingHappens:(NSNotification *)notification
{
BattleObject *battleObject = (BattleObject *) notification.object;
// Do stuff with object
}
You could use NSNotification Center. This allows you to send messages in one object and have multiple other objects react to them.
// The object that wants to receive the message registers with NSNotificationcenter
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(receiveScoreUpdateEvent:)
name:#"scoreUpdateEvent"
object:nil ];
In the same object you need to define the method that your selector points to:
- (void)startLocating:(NSNotification *)notification {
NSNumber *scoreObject = [[notification userInfo] objectForKey:#"score"];
// Do something with the new score
}
Another object can then send a message with the updated score at any time and your HUD would react to it:
[[NSNotificationCenter defaultCenter] postNotificationName:#"scoreUpdateEvent"
object:self userInfo:[NSNumber numberWithInt:5345] forKey:#"score"]];