Cocoa QTMovieView keydown not working - objective-c

I have a QTMovieView control on my cocoa window and it's working great with movies.
Now I want to intercept key down / up events to control the video as I like.
I created a MyMovieView class derived from QTMovieView like this
#interface MyMovieView : QTMovieView
-(BOOL)acceptsFirstResponder;
-(void)keyDown:(NSEvent*)theEvent;
#end
and the code that implements it.
I tried to insert the class name "MyMovieView" into the "Custom Class" field of the Interface Builder inspector for the control QTMovieView but seems like after I close the interface builder, the class gets lost and the "Custom Class" field doesn't remember MyMovieView class.
Am I getting something wrong with the subclass mechanism? I'm a Cocoa newbie

Your code looks fine to me, I took it and shove it in a basic Xcode project with just an NSLog in the keyDown method which logs the key that was pushed. Here is a link to the the Project.

Related

Why Apple's sample code project IKImageViewDemo does not have an AppDelegate class?

I have studying how to use IKImageView in my app. I downloaded the following demo from Apple site.
https://developer.apple.com/library/mac/samplecode/IKImageViewDemo/Introduction/Intro.html#//apple_ref/doc/uid/DTS10004049
One thing I do not understand is: This project has only implemented a Controller class.
#interface Controller : NSObject
{
...
I do not understand how does it work at all. If I create a new project in XCode, it will usually generate an AppDelegate class which implements NSApplicationDelegate interface.
I do not know if I understand the mechanism correctly.
Does the following steps describe how it works?
1) In info.plist it specifies the main bundle is MainMenu.xib.
2) the Window is binded to the Controller like so
3) When the application starts, it loads the Windows from the MainMenu.xib and the Controller class takes over the windows interaction from there.
It's really old sample code. It predates Xcode project templates generating an app delegate for you.
Back then, early Xcode and ProjectBuilder (the old name for it)
Left it up to you to do that.
Lots of older sample code has this sort of thing. As long as things get kickstarted by nib loading, magic happens, objects are instantiated and connected
If you have a simple controller that inherits from NSObject and it has a proxy in you main nib file, it will get created. If you also connect its proxy as delegate to some view or control in the nib, all of that happens.
You don't technically need an object that is the delegate of you NSApplication object. But in reality it is a good best practice and any non trivial app will have that and a lot more.
There's a lot of magic that happens when the C function NSApplicationMain() is called at the launch of your app.
The old and in many ways out if date book Cocoa in a Nutshell covers this well.
Yeah you pretty much describe how it works and what it's doing.
It's relying on the fact that NSApplicationDelegate is an informal protocol and it doesn't declare that Controller conforms to it and is using the NIB to kick-start the app.

Multiple IBOutlets (from different classes) to One Object

Just a quick semantic question, but is it considered OK to have multiple IBOutlets, located in different classes, going to one (for example) NSButton in Interface Builder. The reason I ask is I need to enable and disable an NSButton based on events that happen in different classes. Would multiple IBOutlets be OK, or should I be creating a controller class for the Button that would receive a message telling it to change the sate of the button, resulting in only one IBOutlet?
Thanks in advance.
#Wain
The relevant code for the MergeFilesController.h file:
#property (nonatomic, retain) IBOutlet NSButton *mergeFilesButton;
-(void)setMergeFilesButtonState:(BOOL)yn;
Relevant code for MergeFilesController.m file:
- (IBAction)mergeFiles:(id)sender {
//Code goes here
}
- (void)setMergeFilesButtonState:(BOOL)yn {
[mergeFilesButton setHidden:yn];
}
I have another class (called DragDropController) that controls some drag-and-drop functionality for an NSView. From the DragDropController.m file, I want to be able to change the state of the mergeFilesButton based on some stuff that happens from within the DragDropController class.
It is from the DragDropController class that I was trying to call setMergeFilesButtonState.
You should use a controller class. View classes should be used for displaying and hosting controls. Controls should pass interaction details to the controller. The controller should control all of the views.
DragDropController should be generic and not know about the other controller specifically. Instead it should post a notification as it's state changes and other controllers can observe the notifications to determine when updates should be made to the UI.

Creating a new event in Interface Builder

I am developing a new component to be used in Interface Builder, which subclasses UIPickerView to create an interface that is similar to UIDatePicker but also includes seconds. I would like for the developer who uses my component to be able to drag a new Object from the library, configure it to be a TimePickerView class, and use it from there.
That bit works perfectly, but now I would like to implement some of the events that are available in a standard UIDatePicker, specifically the "Value Changed" event. I am not sure how to declare an event in this manner without using a delegate protocol. I am also not sure how to make XCode aware of events that are available on an object. Therefore, I am really asking three questions:
How can I declare an event, such as the Value Changed event on a UIDatePicker?
How can I fire an event from within my TimePickerView?
How can I make XCode aware of this event so that a developer can easily link an event to a controller?
As this doesn't seem to be easy to do, I suspect there could be a reason for this; therefore I would also appreciate comments on my approach and arguments for why I should create a delegate protocol to make this happen.
In Objective C and cocoa framework there's nothing like declaring an event(as you would do for example in C#), the same behavior of an event is achieved using the delegate pattern(this is how all cocoa class handle events), so to implement a custom events with the delegate pattern you can do in this way, for example :
Protocol and Custom class interface declarations :
#protocol myDelegate <NSObject>
-(void)valueChanged:(double) value;
#end
#interface UAKTestDelegate : UIPickerView
#property(weak) id<myDelegate> delegate;
#end
Somewhere in the implementation (fire the event) :
//Example of firing the event ....
if([[self delegate] respondsToSelector:#selector(valueChanged:)]) {
[[self delegate] valueChanged:1.0];
}
So, this first part of the answer should address the first two questions in your post(create and fire custom events), but the response to the third answer is simply you can't ...
Xcode(in this case interface builder) knows about the events that UIControl(or a subclass of it) implements, but there's no way to tell it about your own custom events.
So i think that in your case (if you can) you could subclass directly UIDatePicker and eventually override valueChanged if you need to.

Add my own event to "Sent Events" in Interface Builder menu for my own custom UIView

I have created a subclass of UIView and I would like to have it publish custom events that show up in Interface Builder (actually Xcode4) the same way that controls like UIButton have a bunch of events in the "Sent Events" area when you right click on a control in the Xcode 4 designer. I know I can use Delegation (via Protocols) or Notification (via the UINotificationCenter) to let the objects using my custom view know when certain things happen, but I would like to know if the "The Target-Action Mechanism" (described in the Cocoa Fundamentals Guide) is appropriate/desirable/possible to use and be integrated with the Xcode designer. Coming from a mostly .NET background, this approach seems to be closely related to the .NET event model and makes the most sense to me.
There's UIControlEventApplicationReserved, which gives you a range of event identifiers that your app can use. However, I don't think there's any way to tell Interface Builder about application-defined events, so you won't get the same support for your events in IB as you find for UIControl's standard events. Instead, you'll have to specify the target and action for each app-defined event in code. (Please, someone correct me if I'm mistaken on this point.) That's not at all difficult, but it is a little different.
A simple way to do this is to extend UIControl instead of UIView this will allow you to add a target to all the default events (same as UIButton etc).
Note: in order for my custom UIControl to handle the events as opposed to the controls I layered on top of it I had to ensure that userInteractionEnabled = NO was set on all the layered controls.
You can do this using an IBOutletCollection. The advantage of this approach is that you can link objects in Interface Builder. The downside is that you can't link directly to IBActions (like UIControl). Here is a clean implementation using a protocol:
ObserverProtocol.h
#protocol ObserverProtocol <NSObject>
- (void)observedObjectChanged:(id)sender;
#end
MyObject.h
#interface MyObject : NSObject
{
#private
IBOutletCollection(id<ObserverProtocol>) NSArray *observers;
}
- (void)objectChanged;
MyObject.m
#implementation MyObject
- (void)objectChanged
{
for (id<ObserverProtocol> observer in observers)
{
if ([observer respondsToSelector:#selector(observedObjectChanged:)])
{
[observer observedObjectChanged:self];
}
}
}
#end
Then you just need to implement ObserverProtocol in classes you want to observe the event (and to do the binding in Interface Builder of course).

Events for custom UIView

What's the best way for registering events for my UIView subclass, so that I can connect them to IBAction-s in interface builder?
Currently I've just got a standard UIView dropped onto my main view and I've set the class to "RadioDial" (my custom class). This displays the view fine, but I have no idea how to get events out of it.
Thanks
Please clarify: do you mean that you would like Interface Builder to offer your view controllers to wire up custom events that your view subclass will be emitting (much like the Button controls allow you to wire up Touch Inside, etc)?
If you need this type of functionality, you will need to use a generalized 'delegate' property on your View combined with a protocol.
#protocol RadioDialDelegate
-(void)dialValueChanged:(id)sender
#end
#interface RadioDial
{
id<RadioDialDelegate> radioDelegate;
}
#property (nonatomic, assign) IBOutlet id<RadioDialDelegate> radioDelegate;
This will allow the controller to wire up to the view (assuming it implements RadioDialDelegate) and receive any events that come out of the view. Alternatively, you can use an untyped delegate and in your View code, use a late bound call:
if([radioDelegate respondsToSelector:#selector(dialValueChanged:)]) {
[radioDelegate dialValueChanged:self];
}
Create a method in your view controller (if nothing else, you should have a RootViewController in you project). Let's say your method is
-(void) buttonClicked { code code code }
In the controller's header file (for example RootViewController.h) you then put:
-(IBAction) buttonClicked;
And in IB you right-click your button/radio dial/whatever. You will see a list of events and you can drag FROM the connector of the event you want your controller to receive, to the object in IB that represents the controler (probably First Responder). This depends on how your IB structure is set up, but it should be straightforward.
Another alternative is to learn how to create UIViews programatically, and forget about IB for the time being. Opinions are divided about whether it's better to learn to use IB at the outset, or whether it's better to learn how to do everything in code and save IB for later. In any case, it's necessary to learn both ways of setting up an interface at some point.