PDA

View Full Version : Cocoa - Responding to Events




ehoskins4
Jun 13, 2008, 10:20 AM
I am just getting started with xcode and cocoa programming. My background is in Windows database products. In the programming environments I am used to, events are provided for placing code to react to things like a window's: onOpen, onGotFocus, onClose, etc. I haven't been able to figure out how to program code that I may want to have happen based on a specific event like a window opening. Seems like something every application would need to do. The only thing I have been able to do is have code respond to a button click. There must be a way to respond to a multitude of other things, but I can't seem to figure out how.



Krevnik
Jun 13, 2008, 10:45 AM
Look into delegates. In Objective-C, you write a delegate for an object that wants to listen to general notifications. The delegate methods are usually found in the class reference of the object. (So methods an NSWindow delegate may implement are listed in the NSWindow class reference)

As for: "Seems like something every application would need to do." You would be surprised. I have yet to write an NSWindow delegate myself. What would I do when the window becomes key (moves to front)? If I want to redraw, why not just respond to something more specific?

MonkeyCookie
Jun 13, 2008, 10:49 AM
I'm also a Windows developer new to Cocoa and Objective-C. From what I understand there are typically two ways of handling events.

First of all, some classes (including classes that inherit NSApplication) use a delegate to handle events. You give it an instance of a delegate class, and it calls methods in the delegate class to handle the events. For example, if a key is pressed, NSApplication (or the inherited class) will call something like OnKeyPressed in the delegate instance, a method which contains your custom code. A delegate doesn't have to be a separate class either. In many Cocoa examples (which I strongly recommend you look at), the class makes itself the delegate, so its own methods are called when the delegate is called. I believe this method of event handling applies to classes like NSApplication, NSWindow, NSView. This delegate mechanism is somewhat similar to the C++ MFC framework for Windows applications, where the programmer overrides member functions to handle events.

The second way of event handling is a notification mechanism, which I'm less familiar with. A class provides some sort of notification object, and any other classes interested in notifications sign themselves up to receive notifications when a particular event occurs. This is more like the way a .NET programmer handles events.

I don't know yet which classes use which event handling method, but I understand that it can easily be found in the class documentation.

I strongly suggest reading Apple's great developer guides at developer.apple.com, which is where I've been learning all this stuff. In order to properly understand event handling, you should read the Introduction to Cocoa Fundamentals guide, which explains all this better than I can. That's where I learned what I know. There's a link at the upper-left to download a PDF, which is in my opinion easier to read and navigate than the web version.

http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/Introduction/chapter_1_section_1.html

robbieduncan
Jun 13, 2008, 11:01 AM
Events are passed to the first responder which will either respond or pass the even down the responder chain. If your code is in the responder chain then you can respond to the even. Simple really

Read This (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/CoreAppArchitecture/chapter_7_section_6.html)

gnasher729
Jun 13, 2008, 11:13 AM
I am just getting started with xcode and cocoa programming. My background is in Windows database products. In the programming environments I am used to, events are provided for placing code to react to things like a window's: onOpen, onGotFocus, onClose, etc. I haven't been able to figure out how to program code that I may want to have happen based on a specific event like a window opening. Seems like something every application would need to do. The only thing I have been able to do is have code respond to a button click. There must be a way to respond to a multitude of other things, but I can't seem to figure out how.

You should first have a look at the documentation of NSWindow. Now the class NSWindow is huge, does tons of things, and even though you could create a subclass and override methods in it, Cocoa uses a different method. NSWindow decides in which situations it wants you (the application developer) to handle a situation. To do that, you create a delegate object and install it into the window by calling [myWindow setDelegate: myDelegate]. The delegate object only implements the dozen methods that are marked as "delegate" methods in NSWindow.

For example, to handle closing a window there are two delegate methods. One is called "windowShouldClose". If the user clicks into the red close button and releases the mouse, NSWindow calls the delegates "windowShouldClose" method. At that point, your code decides whether you actually want the window to close or not. For example, if the window contains a document with unsaved changes, "windowShouldClose" will ask the user whether they want to save the changes, and if they press "Cancel" your delegate method returns "NO" and the window isn't closed. You don't close the window yourself, you only do everything else that needs doing.

The other method is "windowWillClose". NSWindow calls that method just before it closes the window. There is no way to prevent it from closing the window, your delegate had its chance when "windowShouldClose" was called. All you do is clean up everything you want to clean up before the window disappears.

ehoskins4
Jun 13, 2008, 12:18 PM
All of these responses were very helpful. I think i'm on the right track now. I sure appreciate it! I'm really happy to have found this forum. :)

Ed


You should first have a look at the documentation of NSWindow. Now the class NSWindow is huge, does tons of things, and even though you could create a subclass and override methods in it, Cocoa uses a different method. NSWindow decides in which situations it wants you (the application developer) to handle a situation. To do that, you create a delegate object and install it into the window by calling [myWindow setDelegate: myDelegate]. The delegate object only implements the dozen methods that are marked as "delegate" methods in NSWindow.

For example, to handle closing a window there are two delegate methods. One is called "windowShouldClose". If the user clicks into the red close button and releases the mouse, NSWindow calls the delegates "windowShouldClose" method. At that point, your code decides whether you actually want the window to close or not. For example, if the window contains a document with unsaved changes, "windowShouldClose" will ask the user whether they want to save the changes, and if they press "Cancel" your delegate method returns "NO" and the window isn't closed. You don't close the window yourself, you only do everything else that needs doing.

The other method is "windowWillClose". NSWindow calls that method just before it closes the window. There is no way to prevent it from closing the window, your delegate had its chance when "windowShouldClose" was called. All you do is clean up everything you want to clean up before the window disappears.

HiRez
Jun 13, 2008, 12:49 PM
The hard part is knowing which Cocoa objects handle which events, and deciding which delegates you want to send them to (quite often, you will simply use your application controller object or NSDocument subclass). As gnasher says, Cocoa decides at which points it's going to send out events, so you need to decide the proper points that your code needs to execute. Certain actions (user closes window, quits application, drags something from another app, etc.) can generate a number of closely-spaced events where the application will be in slightly different states, so you need to be careful which one you choose. For example, you don't want to try accessing objects bound to a window when you get the message that it did close (because those objects may be invalid or at least not visible), you might want to do that when you get the message that the window will close.