Replace the NSResponder of an existing NSView - objective-c

I have a view in an drawing application, it needs to respond in an other way when an other tool is selected. I thought it would be much nicer to replace the NSResonder of that view in stead of setting every responder method of the view call the new responder method. Is this possible, of is there an other nice solution?

Each NSView object does not "have" an NSResponder. NSResponder is the *superclass from which NSView inherits, so no, it can not be changed. The easiest solution would be just to keep an ivar that tracks which tool is currently selected, then use that ivar to determine what action to take in the NSResponder methods (-mouseDown:, etc.).

Related

How do I allow my NSTableView delegate/datasource handle copy/paste/etc

I have an NSTableView where I'd like to be able to highlight 1 or more rows, and then hit the delete key to delete them, or hit ⌘+C to copy them to the pasteboard.
I've found a suggestion to subclass the NSTableView and then code up a method for
-(void)copy:(id)sender
The documentation says that subclassing the NSTableView is rarely necessary. Instead, use the dataSource or delegate, or subclass a subcomponent. The delegate and dataSource protocols don't handle menu commands or keyboard short cuts. If I try to subclass anyways, I run into a problem where the subclass needs to send a message to the delegate, but my custom methods aren't part of the protocol, so the compiler complains. Rather than fight the design pattern, I'd rather know what the "correct" approach to this problem is.
I solved my problem by declaring the NSTableView's parent window's delegate as the NSTableView's controller (which is also its dataSource and delegate). Now it receives menu actions as part of the responder chain.

What does it mean to delegate to File Owner in my xib file?

I believe that UIView objects can delegate control to views in iOS programming. However, I thought this was already handled by an IBAction associated with an IBOutlet corresponding to the UIView.
In that case, what does it mean to drag a blue line (while pressing Ctrl) from the delegate circle of the UIView in my xib to File Owner?
Isn't the UIView already delegating to my view controller via an IBAction? The code seems to work if I don't specify anything for my UIView's delegate.
"Isn't the UIView already delegating to my view controller via an IBAction? The code seems to work if I don't specify anything for my UIView's delegate".
It looks like you're confusing the idea of the Target-Action Mechanism with delegation. While you could in a way think of target-action as involving “delegation”, it would only be in the most general sense of the word in that it’s the target (generally a controller) that handles and implements the action (the message). However, a Cocoa programmer would probably refrain from explaining the target-action mechanism by using that particular word – delegation – as it would be too easy to confuse it with actual Delegation.
When you “wire up” buttons and controls in the nib file to call IBAction methods in your controller object, that’s just the target-action mechanism at work. As you saw, the code works even if you "don't specify anything for my UIView delegate”, since target-action doesn’t involve delegation (in the Cocoa-sense of the word).
Delegation is generally used as an easier alternative to using subclassing to implement the desired behavior. For example, instead of having to create your own custom subclass of UITableView in order to have it know what data you want it to display, you can simply use the plain UITableView class, set its delegate to a controller class, and have the controller class implement the required/desired designated delegate methods. Using subclassing to accomplish that could potentially get complicated, since when you subclass, you need to have a full understanding of the inheritance chain and how all of the superclasses work.
File's Owner is just a fancy way of disguising the name of the class that the XIB is taking it's references from. When you drag the delegate outlet to your class, it's the equivalent of this line:
[self.myControl setDelegate:self];
When you drag while pressing CNTRL from an IBOutlet or IBAction to a UILabel, UIButton or something else, you are binding events or outlets to your controller.
A delegate sort of a controller that must implement specific functions depending on which type of delegate it is. For example, the UIViewController, which implements the UIViewDelegate protocol, can implement
-(void)viewDidLoad
the YourApplicationDelegate, which implements UIApplicationDelegate must implement
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
So a delegate is just a set of functions which define the behavior of an object, the classes that implement them can change this behavior.

IOS custom button

I need a custom button like Instragram has in profile tab (the buttons that shows the number of photos and followers) but i don't know how to start to implement it.
Do i need to subclass UIButton or is there other way easier?
I think, the easiest approach would be to create a UIButtom with the typeUIButtonTypeCustom and add a subview to it with imageviews and labels as subviews to create the UI. Composition over inheritance.
Subclassing UIButton seems to me to be the obvious solution. I agree that subclassing UIViewController makes no sense. You don't use UIViewController objects to manipulate individual subviews within a view hierarchy controlled by another UIViewController object.
There are plenty of ways to do this, personally I would subclass UIViewController. Then you can edit its .xib in interface builder to make it look however you want and set different values programmatically. Then to detect a tap on the button you can just use the touchesBegan and touchesEnded (I'm pretty sure those aren't complete method names, check in the docs for more info on them) methods. If you want you could also set up a UITapGestureRecognizer for the view instead.

How do run some code when an UIView is loaded on iOS?

I want to run some code when any UIView is loaded from the resources.
How can I do that, without having to modify implementation of each UIView subclass?
Note: subclassing UIView is not an option.
You should subclass UIView and then use your subclass for all your others UIviews
You could consider creating a UIView, which will be the base view class to all your UIView as suggested by #gsempe and implement the willMoveToSuperview: method.
From Documentation.
Tells the view that its superview is
about to change to the specified
superview.
- (void)willMoveToSuperview:(UIView *)newSuperview;
- (void)willMoveToWindow:(UIWindow *)newWindow;
Since we are talking resources and NIB implicitly, I can recollect only two methods in which you would load a view – UIViewController's initWithNibName:bundle or loadNibNamed:owner:options: although there might be some private methods that we aren't provided access to.
So you can think of overriding behavior there. You can create a custom UIViewController subclass that will be the parent for all your view controller's and subclass NSBundle to override loadNibNamed:owner:options:. But this might depend on what kind of task you want to accomplish.
You can try declaring your own category and override a method, but I don't think that would be a good practice. Other way is to extend the UIView subclass and override the method you want. And use that class in your application instead of UIView.
So the approach really depends on your use case.

Why does an NSWindow or NSView instance handle its own key events, and not its delegate?

As a newcomer to Cocoa, I am struggling to understand why the generic NSResponder subclasses implement key events the way they seem to do.
In my program, I have an NSWindow subclass which takes up the whole screen, and must necessarily handle key events. There are several major commands which can change the whole state of the program (e.g. pause a timer when the user hits the spacebar) which it does not make sense to have subviews like an NSTextField handle.
It seems to me that the delegate (controller) should get these events. Instead, I find I have to either write a bunch of messy glue code to have the window (via its keyDown: and interpretKeyEvents: selectors) notify the controller, or I have to just move a bunch of controller code to the NSWindow subclass itself.
This is messy and my gut tells me I'm missing something. Is there a cleaner solution?
If you've set it up correctly, the NSWindow's delegate will receive the messages. Cocoa uses the responder chain to forward messages from the first responder -- the key view for key messages, and the view that was clicked/hovered/etc. for mouse messages -- back through the superviews, up through the window, and eventually to the window's delegate. There's a pretty good diagram of the typical responder chain on Apple's site.
You really should never have to subclass NSWindow unless you're implementing some fancy window drawing or something else along those lines. Cocoa provides the NSWindowController class to behave as a controller for a window and its contents.
The usual pattern is to subclass NSWindowController and add your IBOutlets to it, and then use a NIB to lay out your window contents. You make your NSWindowController subclass the class of the File's Owner proxy in Interface Builder. And you also assign the window's delegate to the window controller so that it can become part of the responder chain. Finally, to create windows, you use NSWindowController's initWithWindowNibName: method, which automates loading the NIB with a new window controller as the file's owner.
I'd recommend reading up on window controllers in the Cocoa documentation, because they provide the missing link you're looking for.