NSControl subclass can't read the target? - objective-c

The following code:
- (void) setTarget:(id)anObject {
NSLog(#"anObject: %#",anObject);
[super setTarget:anObject];
NSLog(#"Target: %#",[self target]);
}
has this output:
anObject: <DropZoneViewController: 0x15dd5770>
Target: (null)
This is in a subclass of NSControl. So what am I doing wrong?
What I'm trying to achieve: I have an NScontrol that accepts dragging objects. When the dragging ends, I'd like to send the control's action to its target. But how do I get the control's action & target if this above doesn't work?

NSControl doesn’t store it’s own target, that is what it’s cell is supposed to do.
So there are two reasons this might fail:
Your control doesn’t have a cell
In this case you really should create a subclass of NSActionCell to implement your control. Your subclass of NSControl shouldn’t do much besides setting up the cell.
If you don’t want to do it the right way by using a NSCell you’ll have to add instance variables to your NSControl subclass to store the target and action and override the getters and setters to use them.
Your cell is not a subclass of NSActionCell. A regular NSCell doesn’t store a target either.
If you’re using a custom cell that is not a subclass of NSActionCell just change it so that it does inherit from NSActionCell instead of NSCell. If you cannot do this (for example because you’re subclassing a NSCell subclass you cannot change) you’ll have to add the instance variables for target and selector to your cell class and override it’s setters and getters.

Related

How to set delegate for subclass

I'm writing own switch class. I'd like to add a delegate to it - examplary if we have UIImagePickerController we add UIImagePickerControllerDelegate to #interface of some viewcontroller and we can set methods like imagePickerControllerDidCancel:(UIImagePickerController *)picker...
I want to do something similar for my class - it's named HSwitch, so I want to add HSwitchDelegate to #interface of some view controller.
I would like to add to this delegate a method valueWasChanged, that I could set in viewController and which would be called each time when slider changes value.
How can I do that? I didn't do it yet, so... please help me :)
Thanks!
If your class is a switch, presumably it inherits from UIControl. If this is the case, don't introduce the complexity of delegates - use target-action instead, and send actions / register targets as you would with any other control. See the UIControl class reference for details. UIControlEventValueChanged would be a suitable event for your needs.

Override addTarget method

I have subclassed UIControl, and would like to override the sendAction:to:forEvent method so that I can send my own customized UIEvent (so that I can retain the UIControlEvents variable). However, since all I have to work with is a UIEvent, I cannot retain the UIControlEvents variable.
Because of this, I figure I need to override the addTarget method so that I can preserve the UIControlEvents variable.
Main Question:
So does anyone know how to implement the addTarget method to preserve the functionality it should without overriding it? Furthermore does anyone know a better solution since apple doesn't give this info (UIControlEvents variable through the UIEvent object) by default.
In your subclass provide your own addTarget method, but do not call super. Save the target and option, and made yourself the target for that option. When the action method gets sent to your for that event you can take whatever action you want.
EDIT: So you have a subclass, and want to save the added targets etc. Declare a mutable array. When you get this message:
- (void)addTarget:(id)target action:(SEL)action forControlEvents(UIControlEvents)controlEvents
in your subclass you add this mutable dictionary as so:
[myArray addObject:[#"target" : target, #"action" : NSStringFromSelector(action), #"event" : [NSValue valueWithBytes:&controlEvents objCType:#encode(controlEvents)]];
While this on first look seems daunting, its not all that complex.
Now we have every registered object that wants to know about every possible control event. Your code can now decide when or if to notify one or more target about any controlEvent by interating through the array and finding each object that want to know about such and such an event.
Your subclass then decides on any event who gets notified about what.

Call method in UITableViewController from custom UITableViewCell

I need to call a method and pass an object from my custom UITableViewClass implementation to my UITableViewController class. I realize creating an instance of the tableViewController in the custom tableViewCell and calling tableViewController's method is a bad practice.
What is the proper way of doing this?
Two magical concepts in Objective-C are Delegation and Notifications.
Delegation allows you to have your controller hook into a weak object referenced in the cell, which avoids a retain cycle, while still allowing you to send messages to it.
Notifications allow your Cell to broadcast a general notification to any classes that are active and listening for it.
Pick one, and whichever is easiest, stick with it. The two are basically equal in this situation.
Having a reference of the tableController inside the cell is indeed Bad practice
You could fix this by implementing a special #protocol for your UITableViewClass
And add a delegate method to it, and then implment the method inside UITableViewController, and since your UITableViewClass delegate is your UITableViewController, then you would call it like
in your UITableViewClass.m
[delegate someMethod:data];

Drag and drop not working for NSTableView

I have implemented drag and drop feature in my application. All the functionality are well but when we drag a image in to NSTableView,
- (BOOL)performDragOperation:(id < NSDraggingInfo >)sender
method is not getting called.
Can any one tell me the reason why this method is not getting called?
Even if I implement this one also...
- (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender
We need a lot more information.
"...but when we drag a image in to NSTableView"
What do you mean by "image", and where (what application) are you dragging this image from? For example, do you mean an image file (Picture.png) from the Finder that you are dragging to the table view in your application? Or from your own application are you dragging some image from one place to your table view?
Is this your own custom subclass of NSTableView? Because that's the only place that you will see -performDragOperation: or -prepareForDragOperation: being called. By default, NSTableView overrides those primitive NSDraggingDestination methods to implement its own tableview-oriented type of methods like Bavarious mentioned (-tableView:validateDrop:proposedRow:proposedDropOperation:, -tableView:acceptDrop:row:dropOperation:, etc.). If you are talking about the fact that these methods aren't being called in an NSTableView subclass, then remember what the documentation states for -prepareForDragOperation::
This method is invoked only if the
most recent draggingEntered: or
draggingUpdated: message returned an
acceptable drag-operation value
So, first, you need to make sure you've registered for the drag types you want, then you need to implement -draggingEntered.
If, on the other hand, you aren't talking about an NSTableView subclass, but an external controller class, then, yes, those performDragOperation: and prepareForDragOperation: aren't called for it. In other words, if you have a controller class, say, MDAppController, it's set to be the delegate and datasource of an NSTableView, the -performDragOperation: and prepareForDragOperation: of MDAppController won't be called. Those methods are meant for NSView-based classes. For that reason, NSTableView has the following method defined in the NSTableViewDataSource protocol: tableView:validateDrop:proposedRow:proposedDropOperation:. If you implement that in your controller class, it should be called, provided you've set the tableView up properly and it's been registered for the types of data you want.

How to access attributes for a UI element in Interface Builder

For example, I have a UISlider that calls - (IBAction)sliderMoved:(id)sender, which performs some task once a new value has been "slid" to through the Value Changed event. But what if I want to do something based on whatever its initial value is?
Hard-coding something to match the default value in Interface Builder would be sloppy and hard to debug later if someone changes the nib file. So, how can I access the default value set for this UISlider in Interface Builder?
AND, more generally speaking, how does one access these attributes for any such UI element? Are there setter/getter methods already synthesized for these?
As Maunil said, Use bindings to connect the UISlider in InterfaceBuilder to a UISlider object in the code. Once this is done, you can access all its methods & properties.
To set the initial value, use the setValue: property of the UISlider, something like:
- (void)viewDidLoad {
...
// where mySlider is declared as a UISlider object and bound to your XIB slider
[mySlider setValue:some_default_value];
...
}
See the UISlider Class Reference documentation for more information.
You can declare the slider in the header file as IBOutlet, and then hook it up in IB. Then you will be able to access all its properties in code.