"will close" handler loops 3 times on quit

I have this handler and logged a value in it. I notice that the value is logged 3 times every time I quit the application. This might be a problem for me because I also write some values to a text file on quit, so I’m figuring that the text file is being written 3 times every time I quit.

on will close theObject
if name of theObject is “mainWindow” then
log “handler is looping!”
end if
end will close

So my question is how do I stop the handler from looping 3 times on quit?

The higher-level problem here is that you want to store data to disk on quit and you’re doing it in the “window will close” handler. If your intent is to write your persistent data on quit, and it’s not a multi-document application, you may wish to do it in “application will quit”.

Here’s a document that brushes over that:

http://developer.apple.com/documentation/Cocoa/Conceptual/AppArchitecture/Tasks/GracefulAppTermination.html#//apple_ref/doc/uid/20001280-1002469

Now, the question is what kind of data you want to store. If your application is a multi-docuument application, the game changes somewhat. If it’s single-window, you probably should do your data save operation in “application will quit” (or “application should quit”, depending on what your application needs to do).

Edit: As for the multiple invocations of that handler, how many windows are there in the application? If there are multiple, what are their names, and do any of them implement that handler with that script? What else can you tell us about your app?

Hi Mikey-San,
thanks for the comments. It is persistent data that I’m writing. There is no need in this application to ask the user to save data. The data from the table is saved without user intervention. It’s a one-window application and I have linked the close button of the window to the “will close” handler and a “tell me to quit” statement inside of it. But before I do the “tell me to quit” statement I write the persistent data to disk in that handler.

I’m very new at this but this handler is called whether I click the close button or choose “quit” from the application menu. I don’t see a reason for another handler to write the data to disk. I read the reference you provided and the only downside to this handler is that you can’t cancel the close or quit operation from it, but that doesn’t matter in my case as I explained earlier there is no need for that.

From reading the reference, the only part I’m not clear on is what happens when the application is running and the user logs out or shuts down their computer. I don’t have any handlers that address that but I’m not sure I need them. I do want the data written to disk in those cases but I’m not entirerly sure if the window “will close” handler is called in that case. I think it probably is but I’m not sure how it works. I’ll manually check that myself to be sure.

Any advice on this is appreciated.

Mikey-San, I just checked. I shut down my computer and the persistent data was written by that “will close” handler as I suspected. I was not issued any warning to save the data, it just saved the data on its own… which is what I want. Do you see any reason why doing it this way is not acceptable?

And also back to my original question, “So my question is how do I stop the handler from looping 3 times on quit?”
My persistent data is not written 3 times to disk… I checked that. But the question still perplexes me in why my logged value is logged 3 times in that handler. Any clarification on that?

Apple specifically designed quit notifications for tasks such as yours. I’d say the burden is on you to demonstrate a reason it’s not acceptable to use them.

Apologies, but I stand by my original assessment: the higher-level issue is that you should be performing your save operation in one of the quit handlers, not a window close handler. (You aren’t document-based, so there’s no reason not to use one of the quit handlers.) There’s nothing wrong with attempting to figure out why that handler is being invoked multiple times, but the actual solution you seek lies elsewhere.

http://catb.org/~esr/faqs/smart-questions.html#goal

Postscript: If you’re absolutely stuck on this window close thing, you might want to provide more information, as I suggested in my earlier post. This will ensure that the forum members have as much information as possible in order to help you.

I'd say the burden is on you to demonstrate a reason it's not acceptable to use them.

There’s many, many handlers to try to learn. I’m glad you pointed me to the documentation. I read the documentation and I mostly understood what it was saying about the purpose of the quit handlers. From what I read their purpose doesn’t apply to my purpose, but since I don’t fully understand everything I was asking if there was something I missed in my interpretation of them. While it may be prudent to follow the guidelines it certainly doesn’t give me any greater understanding of the process to follow them without understanding why I’m following them.

Again, telling me to do something and not explaining why doesn’t help me learn anything.

You’re off on a separate issue. The write stuff or anything else to do with my application has nothing to do with the question. This behavior happens without any other code.

Try this… open an entirely new applescript application. Link your MainMenu.nib to the will close window handler and put the following code in the main.applescript file. Don’t do anything else to this new application. Build the application and run it from the “Run Log” window in xcode. The run log will show the log message 3 times!

on will close theObject
log “closing window”
tell me to quit
end will close

Now the question is why does it loop 3 times! That’s my question. That’s the entire question. There’s nothing more I can tell you!

I’ve investigated more and here’s what I found. I created a new applescript application and linked the handlers for the “file’s owner” and for the “main window” to the applescript. I then put log comments inside each handler in the main applescript file so I could watch when each handler was called. Here’s the results and which object each handler was linked from. (note that in each handler that begins with the word “should” I had to include “return true” inside of the handler to get the process to continue. Obviously the purpose of these “should” handlers is to check if the operation should continue so you need to return true from the handler.)

on application launch
“will open” ← main window
“opened” ← main window
“will finish launching” ← file’s owner
“awake from nib” ← file’s owner
“launched” ← file’s owner
“will become active” ← file’s owner
“became main” ← main window
“became key” ← main window
“activated” ← file’s owner
“idle” ← file’s owner

on quitting the application by using the red close button on the main window
“should close” ← main window
“will close” ← main window
“will close” ← main window
“resigned main” ← main window
“resigned key” ← main window
“should quit after last window closed” ← file’s owner
“should quit” ← file’s owner
“will quit” ← file’s owner
“will close” ← main window

on quitting the application from the “quit” menu item in the application’s menu
“should quit” ← file’s owner
“will quit” ← file’s owner
“will close” ← main window
“will close” ← main window

Notice the “will close” handler in these. When quitting the application from the red close button it is called 3 times, and not 3 times in a row. When using the “quit” menu item it is called 2 times. In both cases it is the last command called before the application quits.

So this was an interesting exercise and I learned a few things… BUT can anybody explain what is happening here with the “will close” handler? It’s the only one that is called multiple times.

I think maybe I’m understanding the “will close” handler. In general it’s called when something is going to be closed. In this case it’s being called from when the main window is being closed, but the main window is part of the MainMenu.nib. Looking inside of the main menu nib file I can see that there’s actually 3 separate nib files inside of it; a classes.nib, a info.nib, and a keyedobjects.nib. That’s what a nib file is anyway; just a collection of other objects which are linked together and perform as one object. So maybe that’s what the “will close” handler is doing. Each time one of the objects of the mainmenu.nib is closed, that handler gets called. Anyway, that’s what I’m beginning to believe. If you can shed any new light on this please speak up!