Logging all cocoa events? - objective-c

I'm doing usability testing and would like to log all user input events: mouse movements, clicks, drags, and keyboard input. I'm not having much luck figuring out how, or finding any code to do so. Any hints? I took a look at the CoreGraphics EventTap mechanisms, but I'm worried that it will be too low-level; I'd like to actually know what particular UI elements the user clicks on.
Edit to clarify:
I'm doing usability testing, so I want to keep track of what parts of the interface the user uses and doesn't use. So, I want to keep track of "Button 'foo' was clicked 7 times at these particular timestamps, the user scrolled through this list and selected such-and-such item" and so forth.

If you're just looking to track them for your application, you could override -[NSApplication sendEvent:]. It's responsible for dispatching all the events your application receives to the appropriate responders.

I think you'll need to do a lot of swizzling.
Try swizzling tryToPerform:with: first; if that doesn't work, you'll need to swizzle such methods as mouseDown:, mouseUp:, the drag event methods, keyDown:, keyUp:, and the undocumented gesture methods.
One complication in the latter solution is that you'll need to swizzle those methods on not just NSResponder, but on several of its subclasses, because many view classes provide their own implementations, which may or may not call up to their ancestors' implementations.

Instruments has a way to record user interface events. It seems like you might be able to use the dtrace calls that underlie this to accomplish what you're going for.

This is completely different than what you're thinking about right now, but consider something like Silverback if you haven't yet.

Related

What's the perferred event to handle the end of user interaction with a UIControl?

I have a view with multiple dynamically created UITextfields and UISegmented controls on it (but for purposes of this question, there could also be UIButtons, UISwitches, UISliders, or anything else that inherits from UIControl). I want to preform an action whenever the user finished interacting with any of the controls, regardless of what subclass of control it belongs to. From looking at other questions, I think I want to use addTarget:action:forControlEvents: to add observers to each of my controls after they are created, but I don't know which event I'm looking for. I've tried all the ones that are listed in the Apple Docs here that seemed relevant but none of them seem to be triggered everytime. I'm looking for something like .LostFocus in VBA, but I can't seem to find out what that is - I know there is a becomeFirstResponder method to make a control active, but I can't find anything like a "lostFirstResponder" event.
I suppose I could use isKindOfClass to tell what kind of control it is, and set up my event accordingly, but that seems a little sloppy and I feel like there should be a more direct way to do it. I could also probably set up a UITapGestureRecognizer and build up something that way, but that still feels like a workaround and not really the way it's supposed to be done.
If you're willing to subclass, you can override -resignFirstResponder to detect lost "focus", and act accordingly. This is probably only useful for things like textfields which can hold first responder status, and would not work for UISwitch for instance.
Since all UIControl objects are just UIViews, you can also override touchesEnded to detect the end of interaction with these elements.. although the more accepted way is to add your dismissal handler method as an action for all the UIControlEvents that indicate end of interaction, or just UIControlEventValueChanged.
More info on UIResponder here from Apple's Documentation:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIResponder_Class/Reference/Reference.html#//apple_ref/occ/instm/UIResponder/resignFirstResponder
Many UIKit classes have delegate methods that indicate when interactions have ended, for instance UITextField has a textFieldDidEndEditing method. UITextView has similar methods.

Multiple IBActions for a single UI event

I'm a bit embarrassed to ask this one... if I want two very different things to happen when, say, a UIButton is used, can I hook this up in Interface Builder? I can't find a way to add multiple actions to the event.
The obvious answer is to have a single action connected, and perform both methods in the same block of code. But I quite liked the button action being connected to 'saveItem' instead of some generic 'buttonPressed' method.
I suppose I could also add the actions in code.
Unfortunately, there's not a way to do this with the builtin UI classes. You'll have to hook up to a single IBAction, then call through to the methods you want to call.

-makeFirstResponder: usage

I am fairly new to cocoa programming and I would like to ask if anyone can explain me how to
-(BOOL)makeFirstResponder:(NSResponder *)responder; method works. I was planning on using it for NSEvent but can anyone show me how to implement it?
I am trying to use the NSResponder class to get me a working -keyDown method.
NSResponder is one of the fundamental classes in Cocoa. Any class that can respond to events like key presses or menu commands should be a subclass of NSResponder. Each responder keeps track of it's "next responder", and each window keeps track of the object that's currently the "first responder". When an event happens in a window, a message is sent to the first responder. If that object handles the message, great. If not, it passes it along to its next responder. This is known as the "responder chain."
Normally, you don't mess much with the responder chain in Cocoa. The first responder is mostly determined by user actions, such as clicking on a control.
It doesn't make sense to 'use it for NSEvent'. NSEvent isn't a responder, but something that enables responders to do their job.
If you describe more clearly what you're trying to accomplish, I'm sure we can point you in the right direction.
You don't usually implement -makeFirstReponder:, you call it to set the input focus to a view. What is it that you really want to achieve?
I am trying to use the NSResponder class to get me a working keyDown method.
That doesn't make sense. “Use” a class?
If you want to respond to key events, you normally should do that in a view that should be capable of becoming the first responder (see the NSView docs).
See also the Event-Handling Guide, the View Programming Guide, and the video for session 145 (“Key Event Handling in Cocoa Applications”) from the WWDC 2010 session videos (which you should be able to access through your developer account even if you didn't go to WWDC last year).

Why does the execution order of touchesBegan, target-action and touchesEnded change with fast touches of UIButton?

UPDATE: With the blush of shame I discovered that the order had nothing to do with the speed of tapping. I was calling the visual code before the super touchesEnded:withEvent call, which was why if you tapped really fast, the display never got a chance to draw the highlighted state before being dismissed again. Because the code that was actually causing the main thread to block just a few milliseconds, the highlighted state would stay visible until the main thread unblocked again, where as if you tapped really fast, it looked like nothing happened at all. Moving the super call up to the top of the overridden method fixed it all. Sorry, if any moderator sees this post it can be deleted. shame
This problem must have been asked a 1000 times at SO, yet I can't find the explanation to match my specific issue.
I have a UIButton subclass with a custom design. Of course the design is custom enough that I can't just use the regular setSomething:forControlState: methods. I need a different backgroundcolor on touch, for one, and some icons that need to flash.
To implement these view changes, I (counter-intuitively) put the display code in (A) touchesBegan:withEvent and (Z) touchesEnded:withEvent:, before calling their respective super methods. Feels weird, but it works as intended, or so it seemed at first.
After implementing addTarget:action:forControlEvents was used to bind the UIControlEventTouchUpInside to the method (X) itemTapped:, I would expect these methods to always fire in the order (A)(X)(Z). However, if you tap the screen real fast (or the mouse in simulator), they fire in the order (A)(Z)(X). Where (A) and (Z) follow each other in such rapid succession, that the whole visual feedback for tapping is invisible. This is unwanted behavior. This also can't be the way to go, for so many apps need similar behavior, right?
So my question to you is: What am I doing wrong? One thing I'm guessing is that the visual appearance of the buttons shouldn't be manipulated in the touchesBegan:withEvent and touchesEnded:withEvent, but then where? Or am I missing some other well known fact?
Thanks for the nudge,
Eric-Paul.
I don't know why the order is different, but here's 2 suggestions to help deal with it.
What visual changes are you making to the button? If it's things like changing title/image/background image, you can do all this by modifying the highlighted state of the button. You can set a few properties like title and background image per-state. When the user's finger is down on the button, the highlighted state is turned on, so any changes you make to this state will be visible at this time. Do note that if you're making use of the selected state on the button, then you'll need to also set up the visual appearance for UIControlStateHighlighted|UIControlStateSelected, otherwise it will default back to inheriting from Normal when both highlighted & selected are on.
The other suggestion is to ditch touchesBegan:withEvent: and touchesEnded:withEvent: and switch over to using the methods inherited from UIControl, namely beginTrackingWithTouch:withEvent: and endTrackingWithTouch:withEvent:. You may also want to implement continueTrackingWithTouch:withEvent: and use the touchInside property to turn off your visual tweaks if the touch leaves the control.

OOP: Designing a menu system

I am currently trying to create a menu system for a game and cannot arrive at any really sound way to do it. There are several menu screens, each of them non-trivial, so that I would like to keep these as separate classes. The main problem I am having is passing control between these menu screens.
I tried building each of the screens as a singleton and call one screen from the other directly, ie. something like [[MainMenu instance] display] in Objective C. This is a bit messy, because (1) I have to write the singleton boilerplate code for each of the menu screens and (2) the classes get dependent on each other, sometimes I have to code around circular dependencies etc.
I thought about making the classes fully static to get around the instance management (which is a bit extra in this case, since there really is just one instance of each screen). But this also looks quite ugly, especially with Objective C having to “fake” class variables by declaring them static.
Then I thought about some “manager” class that would create the instances and pass the control around, but I am not sure introducing an extra class would solve the problem, especially if this class was to be named Manager :-)
I should note that I do have a working system, it just doesn’t feel very nice. By which I mean there is a bit of code duplication going on, if I am not careful the thing might hang, and so on. Any ideas? I am aware that this is underspecified, so that the discussion will probably be more of a brainstorming, but I am interested in the ideas anyway, even if they do not outright solve my problem.
Update: Thank You all for the ideas. What I did in the end:
I reworked the menu contents (buttons, graphics, etc.) to fit under one interface called ScreenView. This is a general interface that looks like this:
#protocol ScreenView
- (void) draw;
- (BOOL) handlesPoint: (CGPoint) p;
- (void) appearWithAnimation;
- (void) disappearWithAnimation;
- (BOOL) hasFinishedAnimating;
#optional
- (void) fingerDown;
- (void) fingerUp;
#end
Thanks to this protocol I was able to throw away all the specific menu screens and create a general menu screen that takes a list of subviews to display and handles all the presentation like drawing, transitions, events and such. This general menu screen does not get subclassed much, because most of the menu screens are happy simply displaying a list of subviews. This would be the V in MVC.
Then I also created a controller class that handles all the events for a certain menu screen. (Obviously the C in MVC.) The root controller class handles the instance management, transitions between menus and some other little things. Most of the menu screens get a customized subclass of the controller that handles the events from the buttons and other subviews.
The number of classes got up, but the code is much cleaner, does not repeat itself and is less prone to errors. The instance management is still not perfect, but I’m reasonably happy with the design. Once again, thank to all who answered.
One of the tricks I learned to decent design is always separate your data from your code. This will do WONDERS for your specific problem.
By this I mean that the menu items (strings) and relationships between the menus should be stored somewhere either in an array or a separate file (and read into an array).
You then use this array to instantiate all your menu classes.
Once you recode it to work this way (I've done this with menus), all your code will fall into place, you'll also factor out--90% of your menuing code (each menu will no longer be it's own class, just the same class instantiated with its own unique data.
The target of the menu items are stored in the "data" as well (as method pointers or class instances).
I think a MenuManager class would be the way to go. You'd have one Menu base class which all the menu screens derive from, and the manager would have a pointer to the currently active menu screen. It could also, for example, keep track of previous menu screens for easy use of back buttons on menu screens in arbitrary menu screen calls. Maybe just use a std::vector for that so you don't have to recreate the previous menu screens when going back (this would also prevent loss of entered information, like in an Options menu with an Advanced submenu).
Putting all the contents of the menus into a dictionary, dumping to a plist and reading each as necessary by the menu screens is likely the simplest route but in all honesty, you should consider taking a more MVC-centric approach to solving the problem. The screens should be for presentation of data not the storage of it. If you provide for a clean separation of the data from the views, the problem solves itself.