How to set delegate for subclass - objective-c

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.

Related

Interaction between Subview and UIViewController with Delegates

I've read a lot of articles to get some information about the whole delegate concept in objective c. At least I think I got the general idea of that. But I didn't found an answer for my question - or I just found it but didn't got it...
In my case I got a custom subview I'm adding programmatically on my UIViewController. I want to have an interaction from the custom UIView to call some methods of the controller. I think it would be better to have a delegate concept instead of making a reference to my UIViewController in the SubView, right?
My question is, isn't it possible to do something with my UIScrollViewDelegate. My UIViewController is implementing some delegate methods because my SubView is a UIScrollView. So would it be possible to add a custom method which I can call with something like:
[self.delegate myCustomMethodOnUIViewController]
Or what would be the best way? Should I set up a protocol and add it as custom delegate to my UIViewController? Do I have to set up then a delegate property on my subview?
Thanks for help!
Andy
If you're adding the UIView as a subview to the UIViewController and you want to execute some methods from the superview in your subview there may be some mistake in your software design.
If there's a necessity to do it, then use the #class variable for circular inclusions and call your methods. To read more about #class directive.
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html
More illustration can be read at the link:
#class vs. #import
You can make it work with delegates and protocols, but make sure you handle memory properly within the same contexts to avoid leaks.

Objective C View to Controller Communication

What is the proper way to accept user input in a view and then transfer it to that view's controller? I know the NotificationCenter is one option, but surely there is a more elegant way to transfer data from a view to its controller?
All help is greatly appreciated and I always accept an answer!
Use the delegate protocol design pattern, or target-action by subclassing UIControl. Think about how a UIButton tells a view controller that it's been pressed. In interface builder, you connect an action - a selector something like touchUpInside: to a target - the view controller that owns it. In non-IB, you directly tell the UIButton what selector and what target to use.
Both methods make sense in different cases. For a UITextField, for example, it makes more sense to use delegation because it's possible for the text field to send you any number of events, such as an event when the user begins editing, ends editing, or types a character.
For a button, it makes more sense to use target-action because there's really only one event expressed in different forms.
For swipes and drags and other gestures, use UIGestureRecognizers.
You're looking for Delegation or a Data Source. You can see more information about this here, Delegation and Data Sources
A brief example of this would be, something along the lines of this:
//MyViewSubclass.h
#protocol MyViewSubclassDelegate
//Implement your delegate methods here.
-(void)didTouchView;
#end
#interface MyViewSubclass {
id<MyViewSubclassDelegate>delegate;
}
#property(nonatomic,assign)id<MyViewSubclassDelegate>delegate;
Of course, #synthesize your delegate in MyViewSubclass.m
Now in the class's header, that you want the delegate of MyViewSubclass to be, you need to conform to the `MyViewSubclassDelegate Protocol.
#import "MyViewSubclass.h"
#interface MyViewController : UIViewController <MyViewSubclassDelegate>
In your #implementation of MyViewController., implement the MyViewSubclassDelegate method of -(void)didTouchView.
When you initialize and create your MyViewSubclass object, you set MyViewController as the delegate:
myViewSubclass.delegate = self // Self being MyViewController.
In your MyViewSubclass, when you're ready to forward any information, or simply want to fire a method you would do [self.delegate didTouchView]
Hope this helps !
You are looking for delegation, where the controller set itselfs as the delegate of the view. You know it from UITableViewDelegate.
Make your view a subclass of UIControl and implement the target/action design pattern - use the sendActionsForControlEvents: method to message the controller.
Often the UIKit objects like UITextField have delegate methods that you can implement to perform your business logic. E.g UITextField has a delegate method called - textFieldDidEndEditing: that gets called after the user has dismissed the keyboard.

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.

Pass data back to the previous controller

I have two controllers in the storyboard, embedded in a NavigationController, and there is a segue to switch between these.
Passing data from the first controller to the second one is pretty straightforward by implementing prepareForSegue, and set the properties of the second controller using segue.destinationViewController.
I should pass back data to the from the second controller to the previous one also. I googled, but I have not found any simple, but working code to demonstrate it.
Would you be so kind give me a simple sample about the best way to do it?
Thanks in advance!
In your second view controller class you create a protocol and delegate. The first view controller will set it self as the delegate in prepareForSegue and implement the protocol methods. The second view controller will then call the methods to pass data back to the first view controller. Here is some code from one of my projects as an example.
#protocol TableSelectorDelegate <NSObject>
#optional
- (void)didMakeSelection:(id)selectionString forType:(NSString *)dataTitle;
- (void)didAddNewValue:(NSString *)newValue forType:(NSString *)dataTitle;
#end
#interface TableSelectorViewController : UITableViewController
#property (nonatomic, weak) id<TableSelectorDelegate> delegate;
#end
when you set the data you're passing to the second controller you can also set a pointer to the previous one.
The "recommended" way of doing this is using a delegate. Have the first view controller set itself as the delegate of the new view controller during the -prepareForSegue: call, then when you're done, you call whatever delegate methods you've defined.
This is a bit more work than tightly coupling the two controllers, but it actually saves time if you ever find you need to use the controller in a slightly different way. If you watch the WWDC'11 video on using IB and Storyboards, they actually go through this pattern in depth and include code examples and demos, so I recommend taking a look at that.
I've been studying all of the variants to this question of how to pass data from one view controller to another and have come to see that Apple's Second iOS App Tutorial has not only the code but a lovely explanation of everything involved.

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.